diff --git a/.gitignore b/.gitignore
index 18cd25a69..f385e3dad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -245,4 +245,6 @@ launchSettings.json
/Tests/ApplicationTests/Files/replay.json
/GameLogServer/game_log_server_env
.idea/*
-*.db
\ No newline at end of file
+*.db
+/Data/IW4MAdmin_Migration.db-shm
+/Data/IW4MAdmin_Migration.db-wal
diff --git a/Application/Configuration/LoggingConfiguration.json b/Application/Configuration/LoggingConfiguration.json
index 9c4bd9fc6..f6290ffca 100644
--- a/Application/Configuration/LoggingConfiguration.json
+++ b/Application/Configuration/LoggingConfiguration.json
@@ -3,7 +3,13 @@
"Using": [
"Serilog.Sinks.File"
],
- "MinimumLevel": "Information",
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "System": "Warning",
+ "Microsoft": "Warning"
+ }
+ },
"WriteTo": [
{
"Name": "File",
diff --git a/Data/Data.csproj b/Data/Data.csproj
index 6697f1ce8..351ce099b 100644
--- a/Data/Data.csproj
+++ b/Data/Data.csproj
@@ -8,62 +8,9 @@
RaidMax.IW4MAdmin.Data
RaidMax.IW4MAdmin.Data
- 1.0.1
+ 1.0.3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.Designer.cs b/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.Designer.cs
new file mode 100644
index 000000000..f7c156d48
--- /dev/null
+++ b/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.Designer.cs
@@ -0,0 +1,1283 @@
+//
+using System;
+using Data.MigrationContext;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Data.Migrations.MySql
+{
+ [DbContext(typeof(MySqlDatabaseContext))]
+ [Migration("20210628153649_AddWeaponReferenceToEFClientKill")]
+ partial class AddWeaponReferenceToEFClientKill
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "3.1.10")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b =>
+ {
+ b.Property("ACSnapshotVector3Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SnapshotId")
+ .HasColumnType("int");
+
+ b.Property("Vector3Id")
+ .HasColumnType("int");
+
+ b.HasKey("ACSnapshotVector3Id");
+
+ b.HasIndex("SnapshotId");
+
+ b.HasIndex("Vector3Id");
+
+ b.ToTable("EFACSnapshotVector3");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClient", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AliasLinkId")
+ .HasColumnType("int");
+
+ b.Property("Connections")
+ .HasColumnType("int");
+
+ b.Property("CurrentAliasId")
+ .HasColumnType("int");
+
+ b.Property("FirstConnection")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastConnection")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("Masked")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("NetworkId")
+ .HasColumnType("bigint");
+
+ b.Property("Password")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("PasswordSalt")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("TotalConnectionTime")
+ .HasColumnType("int");
+
+ b.HasKey("ClientId");
+
+ b.HasIndex("AliasLinkId");
+
+ b.HasIndex("CurrentAliasId");
+
+ b.HasIndex("NetworkId")
+ .IsUnique();
+
+ b.ToTable("EFClients");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClientKill", b =>
+ {
+ b.Property("KillId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AttackerId")
+ .HasColumnType("int");
+
+ b.Property("Damage")
+ .HasColumnType("int");
+
+ b.Property("DeathOriginVector3Id")
+ .HasColumnType("int");
+
+ b.Property("DeathType")
+ .HasColumnType("int");
+
+ b.Property("Fraction")
+ .HasColumnType("double");
+
+ b.Property("HitLoc")
+ .HasColumnType("int");
+
+ b.Property("IsKill")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("KillOriginVector3Id")
+ .HasColumnType("int");
+
+ b.Property("Map")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("VictimId")
+ .HasColumnType("int");
+
+ b.Property("ViewAnglesVector3Id")
+ .HasColumnType("int");
+
+ b.Property("VisibilityPercentage")
+ .HasColumnType("double");
+
+ b.Property("Weapon")
+ .HasColumnType("int");
+
+ b.Property("WeaponReference")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("When")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("KillId");
+
+ b.HasIndex("AttackerId");
+
+ b.HasIndex("DeathOriginVector3Id");
+
+ b.HasIndex("KillOriginVector3Id");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("VictimId");
+
+ b.HasIndex("ViewAnglesVector3Id");
+
+ b.ToTable("EFClientKills");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClientMessage", b =>
+ {
+ b.Property("MessageId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("Message")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("SentIngame")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("TimeSent")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("MessageId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("TimeSent");
+
+ b.ToTable("EFClientMessages");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b =>
+ {
+ b.Property("SnapshotId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("CurrentSessionLength")
+ .HasColumnType("int");
+
+ b.Property("CurrentStrain")
+ .HasColumnType("double");
+
+ b.Property("CurrentViewAngleId")
+ .HasColumnType("int");
+
+ b.Property("Deaths")
+ .HasColumnType("int");
+
+ b.Property("Distance")
+ .HasColumnType("double");
+
+ b.Property("EloRating")
+ .HasColumnType("double");
+
+ b.Property("HitDestinationId")
+ .HasColumnType("int");
+
+ b.Property("HitLocation")
+ .HasColumnType("int");
+
+ b.Property("HitOriginId")
+ .HasColumnType("int");
+
+ b.Property("HitType")
+ .HasColumnType("int");
+
+ b.Property("Hits")
+ .HasColumnType("int");
+
+ b.Property("Kills")
+ .HasColumnType("int");
+
+ b.Property("LastStrainAngleId")
+ .HasColumnType("int");
+
+ b.Property("RecoilOffset")
+ .HasColumnType("double");
+
+ b.Property("SessionAngleOffset")
+ .HasColumnType("double");
+
+ b.Property("SessionAverageSnapValue")
+ .HasColumnType("double");
+
+ b.Property("SessionSPM")
+ .HasColumnType("double");
+
+ b.Property("SessionScore")
+ .HasColumnType("int");
+
+ b.Property("SessionSnapHits")
+ .HasColumnType("int");
+
+ b.Property("StrainAngleBetween")
+ .HasColumnType("double");
+
+ b.Property("TimeSinceLastEvent")
+ .HasColumnType("int");
+
+ b.Property("WeaponId")
+ .HasColumnType("int");
+
+ b.Property("When")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("SnapshotId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("CurrentViewAngleId");
+
+ b.HasIndex("HitDestinationId");
+
+ b.HasIndex("HitOriginId");
+
+ b.HasIndex("LastStrainAngleId");
+
+ b.ToTable("EFACSnapshot");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b =>
+ {
+ b.Property("ClientHitStatisticId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DamageInflicted")
+ .HasColumnType("int");
+
+ b.Property("DamageReceived")
+ .HasColumnType("int");
+
+ b.Property("DeathCount")
+ .HasColumnType("int");
+
+ b.Property("HitCount")
+ .HasColumnType("int");
+
+ b.Property("HitLocationId")
+ .HasColumnType("int");
+
+ b.Property("KillCount")
+ .HasColumnType("int");
+
+ b.Property("MeansOfDeathId")
+ .HasColumnType("int");
+
+ b.Property("ReceivedHitCount")
+ .HasColumnType("int");
+
+ b.Property("Score")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("SuicideCount")
+ .HasColumnType("int");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UsageSeconds")
+ .HasColumnType("int");
+
+ b.Property("WeaponAttachmentComboId")
+ .HasColumnType("int");
+
+ b.Property("WeaponId")
+ .HasColumnType("int");
+
+ b.HasKey("ClientHitStatisticId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("HitLocationId");
+
+ b.HasIndex("MeansOfDeathId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("WeaponAttachmentComboId");
+
+ b.HasIndex("WeaponId");
+
+ b.ToTable("EFClientHitStatistics");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b =>
+ {
+ b.Property("ClientRankingHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Newest")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("PerformanceMetric")
+ .HasColumnType("double");
+
+ b.Property("Ranking")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ZScore")
+ .HasColumnType("double");
+
+ b.HasKey("ClientRankingHistoryId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("Ranking");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("UpdatedDateTime");
+
+ b.HasIndex("ZScore");
+
+ b.ToTable("EFClientRankingHistory");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b =>
+ {
+ b.Property("RatingHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.HasKey("RatingHistoryId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("EFClientRatingHistory");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AverageSnapValue")
+ .HasColumnType("double");
+
+ b.Property("Deaths")
+ .HasColumnType("int");
+
+ b.Property("EloRating")
+ .HasColumnType("double");
+
+ b.Property("Kills")
+ .HasColumnType("int");
+
+ b.Property("MaxStrain")
+ .HasColumnType("double");
+
+ b.Property("RollingWeightedKDR")
+ .HasColumnType("double");
+
+ b.Property("SPM")
+ .HasColumnType("double");
+
+ b.Property("Skill")
+ .HasColumnType("double");
+
+ b.Property("SnapHitCount")
+ .HasColumnType("int");
+
+ b.Property("TimePlayed")
+ .HasColumnType("int");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ZScore")
+ .HasColumnType("double");
+
+ b.HasKey("ClientId", "ServerId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("ZScore");
+
+ b.HasIndex("ClientId", "TimePlayed", "ZScore");
+
+ b.ToTable("EFClientStatistics");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b =>
+ {
+ b.Property("HitLocationCountId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("EFClientStatisticsClientId")
+ .HasColumnName("EFClientStatisticsClientId")
+ .HasColumnType("int");
+
+ b.Property("EFClientStatisticsServerId")
+ .HasColumnName("EFClientStatisticsServerId")
+ .HasColumnType("bigint");
+
+ b.Property("HitCount")
+ .HasColumnType("int");
+
+ b.Property("HitOffsetAverage")
+ .HasColumnType("float");
+
+ b.Property("Location")
+ .HasColumnType("int");
+
+ b.Property("MaxAngleDistance")
+ .HasColumnType("float");
+
+ b.HasKey("HitLocationCountId");
+
+ b.HasIndex("EFClientStatisticsServerId");
+
+ b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId");
+
+ b.ToTable("EFHitLocationCounts");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b =>
+ {
+ b.Property("RatingId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ActivityAmount")
+ .HasColumnType("int");
+
+ b.Property("Newest")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Performance")
+ .HasColumnType("double");
+
+ b.Property("Ranking")
+ .HasColumnType("int");
+
+ b.Property("RatingHistoryId")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("When")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("RatingId");
+
+ b.HasIndex("RatingHistoryId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("Performance", "Ranking", "When");
+
+ b.HasIndex("When", "ServerId", "Performance", "ActivityAmount");
+
+ b.ToTable("EFRating");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b =>
+ {
+ b.Property("HitLocationId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("HitLocationId");
+
+ b.HasIndex("Name");
+
+ b.ToTable("EFHitLocations");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b =>
+ {
+ b.Property("MapId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("MapId");
+
+ b.ToTable("EFMaps");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b =>
+ {
+ b.Property("MeansOfDeathId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("MeansOfDeathId");
+
+ b.ToTable("EFMeansOfDeath");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b =>
+ {
+ b.Property("WeaponId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("WeaponId");
+
+ b.HasIndex("Name");
+
+ b.ToTable("EFWeapons");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b =>
+ {
+ b.Property("WeaponAttachmentId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("WeaponAttachmentId");
+
+ b.ToTable("EFWeaponAttachments");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b =>
+ {
+ b.Property("WeaponAttachmentComboId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Attachment1Id")
+ .HasColumnType("int");
+
+ b.Property("Attachment2Id")
+ .HasColumnType("int");
+
+ b.Property("Attachment3Id")
+ .HasColumnType("int");
+
+ b.Property("CreatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Game")
+ .HasColumnType("int");
+
+ b.Property("UpdatedDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("WeaponAttachmentComboId");
+
+ b.HasIndex("Attachment1Id");
+
+ b.HasIndex("Attachment2Id");
+
+ b.HasIndex("Attachment3Id");
+
+ b.ToTable("EFWeaponAttachmentCombos");
+ });
+
+ modelBuilder.Entity("Data.Models.EFAlias", b =>
+ {
+ b.Property("AliasId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("DateAdded")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IPAddress")
+ .HasColumnType("int");
+
+ b.Property("LinkId")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(24) CHARACTER SET utf8mb4")
+ .HasMaxLength(24);
+
+ b.Property("SearchableName")
+ .HasColumnType("varchar(24) CHARACTER SET utf8mb4")
+ .HasMaxLength(24);
+
+ b.HasKey("AliasId");
+
+ b.HasIndex("IPAddress");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("Name");
+
+ b.HasIndex("SearchableName");
+
+ b.HasIndex("Name", "IPAddress")
+ .IsUnique();
+
+ b.ToTable("EFAlias");
+ });
+
+ modelBuilder.Entity("Data.Models.EFAliasLink", b =>
+ {
+ b.Property("AliasLinkId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("AliasLinkId");
+
+ b.ToTable("EFAliasLinks");
+ });
+
+ modelBuilder.Entity("Data.Models.EFChangeHistory", b =>
+ {
+ b.Property("ChangeHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Comment")
+ .HasColumnType("varchar(128) CHARACTER SET utf8mb4")
+ .HasMaxLength(128);
+
+ b.Property("CurrentValue")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("ImpersonationEntityId")
+ .HasColumnType("int");
+
+ b.Property("OriginEntityId")
+ .HasColumnType("int");
+
+ b.Property("PreviousValue")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("TargetEntityId")
+ .HasColumnType("int");
+
+ b.Property("TimeChanged")
+ .HasColumnType("datetime(6)");
+
+ b.Property("TypeOfChange")
+ .HasColumnType("int");
+
+ b.HasKey("ChangeHistoryId");
+
+ b.ToTable("EFChangeHistory");
+ });
+
+ modelBuilder.Entity("Data.Models.EFMeta", b =>
+ {
+ b.Property("MetaId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ClientId")
+ .HasColumnType("int");
+
+ b.Property("Created")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Extra")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasColumnType("varchar(32) CHARACTER SET utf8mb4")
+ .HasMaxLength(32);
+
+ b.Property("LinkedMetaId")
+ .HasColumnType("int");
+
+ b.Property("Updated")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.HasKey("MetaId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("Key");
+
+ b.HasIndex("LinkedMetaId");
+
+ b.ToTable("EFMeta");
+ });
+
+ modelBuilder.Entity("Data.Models.EFPenalty", b =>
+ {
+ b.Property("PenaltyId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AutomatedOffense")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("Expires")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsEvadedOffense")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LinkId")
+ .HasColumnType("int");
+
+ b.Property("OffenderId")
+ .HasColumnType("int");
+
+ b.Property("Offense")
+ .IsRequired()
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("PunisherId")
+ .HasColumnType("int");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.Property("When")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("PenaltyId");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("OffenderId");
+
+ b.HasIndex("PunisherId");
+
+ b.ToTable("EFPenalties");
+ });
+
+ modelBuilder.Entity("Data.Models.Server.EFServer", b =>
+ {
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("EndPoint")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("GameName")
+ .HasColumnType("int");
+
+ b.Property("HostName")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("IsPasswordProtected")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Port")
+ .HasColumnType("int");
+
+ b.HasKey("ServerId");
+
+ b.ToTable("EFServers");
+ });
+
+ modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b =>
+ {
+ b.Property("StatisticId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("TotalKills")
+ .HasColumnType("bigint");
+
+ b.Property("TotalPlayTime")
+ .HasColumnType("bigint");
+
+ b.HasKey("StatisticId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFServerStatistics");
+ });
+
+ modelBuilder.Entity("Data.Models.Vector3", b =>
+ {
+ b.Property("Vector3Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("X")
+ .HasColumnType("float");
+
+ b.Property("Y")
+ .HasColumnType("float");
+
+ b.Property("Z")
+ .HasColumnType("float");
+
+ b.HasKey("Vector3Id");
+
+ b.ToTable("Vector3");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b =>
+ {
+ b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot")
+ .WithMany("PredictedViewAngles")
+ .HasForeignKey("SnapshotId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "Vector")
+ .WithMany()
+ .HasForeignKey("Vector3Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClient", b =>
+ {
+ b.HasOne("Data.Models.EFAliasLink", "AliasLink")
+ .WithMany()
+ .HasForeignKey("AliasLinkId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.EFAlias", "CurrentAlias")
+ .WithMany()
+ .HasForeignKey("CurrentAliasId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClientKill", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Attacker")
+ .WithMany()
+ .HasForeignKey("AttackerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "DeathOrigin")
+ .WithMany()
+ .HasForeignKey("DeathOriginVector3Id");
+
+ b.HasOne("Data.Models.Vector3", "KillOrigin")
+ .WithMany()
+ .HasForeignKey("KillOriginVector3Id");
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.EFClient", "Victim")
+ .WithMany()
+ .HasForeignKey("VictimId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "ViewAngles")
+ .WithMany()
+ .HasForeignKey("ViewAnglesVector3Id");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClientMessage", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "CurrentViewAngle")
+ .WithMany()
+ .HasForeignKey("CurrentViewAngleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "HitDestination")
+ .WithMany()
+ .HasForeignKey("HitDestinationId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "HitOrigin")
+ .WithMany()
+ .HasForeignKey("HitOriginId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Vector3", "LastStrainAngle")
+ .WithMany()
+ .HasForeignKey("LastStrainAngleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation")
+ .WithMany()
+ .HasForeignKey("HitLocationId");
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath")
+ .WithMany()
+ .HasForeignKey("MeansOfDeathId");
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId");
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo")
+ .WithMany()
+ .HasForeignKey("WeaponAttachmentComboId");
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon")
+ .WithMany()
+ .HasForeignKey("WeaponId");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("EFClientStatisticsClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("EFClientStatisticsServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null)
+ .WithMany("HitLocations")
+ .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b =>
+ {
+ b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory")
+ .WithMany("Ratings")
+ .HasForeignKey("RatingHistoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b =>
+ {
+ b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1")
+ .WithMany()
+ .HasForeignKey("Attachment1Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2")
+ .WithMany()
+ .HasForeignKey("Attachment2Id");
+
+ b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3")
+ .WithMany()
+ .HasForeignKey("Attachment3Id");
+ });
+
+ modelBuilder.Entity("Data.Models.EFAlias", b =>
+ {
+ b.HasOne("Data.Models.EFAliasLink", "Link")
+ .WithMany("Children")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.EFMeta", b =>
+ {
+ b.HasOne("Data.Models.Client.EFClient", "Client")
+ .WithMany("Meta")
+ .HasForeignKey("ClientId");
+
+ b.HasOne("Data.Models.EFMeta", "LinkedMeta")
+ .WithMany()
+ .HasForeignKey("LinkedMetaId")
+ .OnDelete(DeleteBehavior.SetNull);
+ });
+
+ modelBuilder.Entity("Data.Models.EFPenalty", b =>
+ {
+ b.HasOne("Data.Models.EFAliasLink", "Link")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.EFClient", "Offender")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("OffenderId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+
+ b.HasOne("Data.Models.Client.EFClient", "Punisher")
+ .WithMany("AdministeredPenalties")
+ .HasForeignKey("PunisherId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b =>
+ {
+ b.HasOne("Data.Models.Server.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.cs b/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.cs
new file mode 100644
index 000000000..d26985c04
--- /dev/null
+++ b/Data/Migrations/MySql/20210628153649_AddWeaponReferenceToEFClientKill.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Data.Migrations.MySql
+{
+ public partial class AddWeaponReferenceToEFClientKill : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "WeaponReference",
+ table: "EFClientKills",
+ nullable: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "WeaponReference",
+ table: "EFClientKills");
+ }
+ }
+}
diff --git a/Data/Migrations/MySql/20210628160144_AddWeaponReferenceAndServerIdToEFACSnapshot.Designer.cs b/Data/Migrations/MySql/20210628160144_AddWeaponReferenceAndServerIdToEFACSnapshot.Designer.cs
new file mode 100644
index 000000000..ca9412b9a
--- /dev/null
+++ b/Data/Migrations/MySql/20210628160144_AddWeaponReferenceAndServerIdToEFACSnapshot.Designer.cs
@@ -0,0 +1,1295 @@
+//
+using System;
+using Data.MigrationContext;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Data.Migrations.MySql
+{
+ [DbContext(typeof(MySqlDatabaseContext))]
+ [Migration("20210628160144_AddWeaponReferenceAndServerIdToEFACSnapshot")]
+ partial class AddWeaponReferenceAndServerIdToEFACSnapshot
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "3.1.10")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b =>
+ {
+ b.Property("ACSnapshotVector3Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SnapshotId")
+ .HasColumnType("int");
+
+ b.Property("Vector3Id")
+ .HasColumnType("int");
+
+ b.HasKey("ACSnapshotVector3Id");
+
+ b.HasIndex("SnapshotId");
+
+ b.HasIndex("Vector3Id");
+
+ b.ToTable("EFACSnapshotVector3");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClient", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AliasLinkId")
+ .HasColumnType("int");
+
+ b.Property("Connections")
+ .HasColumnType("int");
+
+ b.Property("CurrentAliasId")
+ .HasColumnType("int");
+
+ b.Property("FirstConnection")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastConnection")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("Masked")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("NetworkId")
+ .HasColumnType("bigint");
+
+ b.Property("Password")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("PasswordSalt")
+ .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+ b.Property("TotalConnectionTime")
+ .HasColumnType("int");
+
+ b.HasKey("ClientId");
+
+ b.HasIndex("AliasLinkId");
+
+ b.HasIndex("CurrentAliasId");
+
+ b.HasIndex("NetworkId")
+ .IsUnique();
+
+ b.ToTable("EFClients");
+ });
+
+ modelBuilder.Entity("Data.Models.Client.EFClientKill", b =>
+ {
+ b.Property("KillId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ b.Property("Active")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AttackerId")
+ .HasColumnType("int");
+
+ b.Property("Damage")
+ .HasColumnType("int");
+
+ b.Property("DeathOriginVector3Id")
+ .HasColumnType("int");
+
+ b.Property("DeathType")
+ .HasColumnType("int");
+
+ b.Property("Fraction")
+ .HasColumnType("double");
+
+ b.Property("HitLoc")
+ .HasColumnType("int");
+
+ b.Property("IsKill")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("KillOriginVector3Id")
+ .HasColumnType("int");
+
+ b.Property("Map")
+ .HasColumnType("int");
+
+ b.Property("ServerId")
+ .HasColumnType("bigint");
+
+ b.Property("VictimId")
+ .HasColumnType("int");
+
+ b.Property("ViewAnglesVector3Id")
+ .HasColumnType("int");
+
+ b.Property("VisibilityPercentage")
+ .HasColumnType("double");
+
+ b.Property("Weapon")
+ .HasColumnType("int");
+
+ b.Property