diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj
index fc817db32..91e3147a4 100644
--- a/Plugins/AutomessageFeed/AutomessageFeed.csproj
+++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj
index 2c925e28a..e5bca04cc 100644
--- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj
+++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/Plugins/LiveRadar/LiveRadar.csproj b/Plugins/LiveRadar/LiveRadar.csproj
index 7f0665731..03819637e 100644
--- a/Plugins/LiveRadar/LiveRadar.csproj
+++ b/Plugins/LiveRadar/LiveRadar.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/Plugins/Login/Login.csproj b/Plugins/Login/Login.csproj
index 49933244e..d76e43534 100644
--- a/Plugins/Login/Login.csproj
+++ b/Plugins/Login/Login.csproj
@@ -23,7 +23,7 @@
-
+
diff --git a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj
index 1a8aa316f..8cbfdc5a9 100644
--- a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj
+++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs
index 0a2a9c03d..ef6f27df8 100644
--- a/Plugins/Stats/Helpers/StatManager.cs
+++ b/Plugins/Stats/Helpers/StatManager.cs
@@ -1171,7 +1171,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
stats.EloRating = 200;
}
- public async Task AddMessageAsync(int clientId, long serverId, string message)
+ public async Task AddMessageAsync(int clientId, long serverId, bool sentIngame, string message)
{
// the web users can have no account
if (clientId < 1)
@@ -1179,18 +1179,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
return;
}
- using (var ctx = _contextFactory.CreateContext(enableTracking: false))
+ await using var ctx = _contextFactory.CreateContext(enableTracking: false);
+ ctx.Set().Add(new EFClientMessage()
{
- ctx.Set().Add(new EFClientMessage()
- {
- ClientId = clientId,
- Message = message,
- ServerId = serverId,
- TimeSent = DateTime.UtcNow
- });
+ ClientId = clientId,
+ Message = message,
+ ServerId = serverId,
+ TimeSent = DateTime.UtcNow,
+ SentIngame = sentIngame
+ });
- await ctx.SaveChangesAsync();
- }
+ await ctx.SaveChangesAsync();
}
public async Task Sync(Server sv)
diff --git a/Plugins/Stats/Models/EFClientMessage.cs b/Plugins/Stats/Models/EFClientMessage.cs
index 4a4106c1e..49c2a9316 100644
--- a/Plugins/Stats/Models/EFClientMessage.cs
+++ b/Plugins/Stats/Models/EFClientMessage.cs
@@ -17,5 +17,6 @@ namespace IW4MAdmin.Plugins.Stats.Models
public virtual EFClient Client { get; set; }
public string Message { get; set; }
public DateTime TimeSent { get; set; }
+ public bool SentIngame { get; set; }
}
}
diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs
index 22545df97..74983b061 100644
--- a/Plugins/Stats/Plugin.cs
+++ b/Plugins/Stats/Plugin.cs
@@ -15,6 +15,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
+using SharedLibraryCore.Commands;
namespace IW4MAdmin.Plugins.Stats
{
@@ -56,8 +57,6 @@ namespace IW4MAdmin.Plugins.Stats
case GameEvent.EventType.Start:
Manager.AddServer(S);
break;
- case GameEvent.EventType.Stop:
- break;
case GameEvent.EventType.Disconnect:
await Manager.RemovePlayer(E.Origin);
break;
@@ -65,7 +64,7 @@ namespace IW4MAdmin.Plugins.Stats
if (!string.IsNullOrEmpty(E.Data) &&
E.Origin.ClientId > 1)
{
- await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), E.Data);
+ await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), true, E.Data);
}
break;
case GameEvent.EventType.MapChange:
@@ -76,21 +75,13 @@ namespace IW4MAdmin.Plugins.Stats
case GameEvent.EventType.MapEnd:
await Manager.Sync(S);
break;
- case GameEvent.EventType.JoinTeam:
- break;
- case GameEvent.EventType.Broadcast:
- break;
- case GameEvent.EventType.Tell:
- break;
- case GameEvent.EventType.Kick:
- break;
- case GameEvent.EventType.Ban:
- break;
- case GameEvent.EventType.Unknown:
- break;
- case GameEvent.EventType.Report:
- break;
- case GameEvent.EventType.Flag:
+ case GameEvent.EventType.Command:
+ var shouldPersist = !string.IsNullOrEmpty(E.Data) &&
+ E.Extra is SayCommand;
+ if (shouldPersist)
+ {
+ await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), false, E.Data);
+ }
break;
case GameEvent.EventType.ScriptKill:
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
diff --git a/Plugins/Stats/Stats.csproj b/Plugins/Stats/Stats.csproj
index 1c379fca9..2e2304f13 100644
--- a/Plugins/Stats/Stats.csproj
+++ b/Plugins/Stats/Stats.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs
index 7af3cfcc0..34586ded8 100644
--- a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs
+++ b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs
@@ -81,7 +81,8 @@ namespace StatsWeb
When = _message.TimeSent,
Message = _message.Message,
ServerName = query.IsProfileMeta ? "" : _message.Server.HostName,
- GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value
+ GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value,
+ SentIngame = _message.SentIngame
});
if (query.Direction == SharedLibraryCore.Dtos.SortDirection.Descending)
diff --git a/Plugins/Web/StatsWeb/StatsWeb.csproj b/Plugins/Web/StatsWeb/StatsWeb.csproj
index 75017f636..19bd04530 100644
--- a/Plugins/Web/StatsWeb/StatsWeb.csproj
+++ b/Plugins/Web/StatsWeb/StatsWeb.csproj
@@ -14,7 +14,7 @@
Always
-
+
diff --git a/Plugins/Welcome/Welcome.csproj b/Plugins/Welcome/Welcome.csproj
index ebdc6a2e9..44436dc56 100644
--- a/Plugins/Welcome/Welcome.csproj
+++ b/Plugins/Welcome/Welcome.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs b/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs
index 8ca3693cf..17f90e700 100644
--- a/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs
+++ b/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs
@@ -27,6 +27,11 @@ namespace SharedLibraryCore.Dtos.Meta.Responses
/// indicates if the chat message is a quick message phrase
///
public bool IsQuickMessage { get; set; }
+
+ ///
+ /// indicates if the message was sent ingame
+ ///
+ public bool SentIngame { get; set; }
public string HiddenMessage => string.Concat(Enumerable.Repeat('●', Message.Length));
}
diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs
new file mode 100644
index 000000000..07205a944
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs
@@ -0,0 +1,930 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using SharedLibraryCore.Database;
+
+namespace SharedLibraryCore.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20201118023106_AddSentIngameFlagToClientMessage")]
+ partial class AddSentIngameFlagToClientMessage
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "3.1.7");
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
+ {
+ b.Property("SnapshotId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ClientId")
+ .HasColumnType("INTEGER");
+
+ b.Property("CurrentSessionLength")
+ .HasColumnType("INTEGER");
+
+ b.Property("CurrentStrain")
+ .HasColumnType("REAL");
+
+ b.Property("CurrentViewAngleId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Deaths")
+ .HasColumnType("INTEGER");
+
+ b.Property("Distance")
+ .HasColumnType("REAL");
+
+ b.Property("EloRating")
+ .HasColumnType("REAL");
+
+ b.Property("HitDestinationId")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitLocation")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitOriginId")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitType")
+ .HasColumnType("INTEGER");
+
+ b.Property("Hits")
+ .HasColumnType("INTEGER");
+
+ b.Property("Kills")
+ .HasColumnType("INTEGER");
+
+ b.Property("LastStrainAngleId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RecoilOffset")
+ .HasColumnType("REAL");
+
+ b.Property("SessionAngleOffset")
+ .HasColumnType("REAL");
+
+ b.Property("SessionAverageSnapValue")
+ .HasColumnType("REAL");
+
+ b.Property("SessionSPM")
+ .HasColumnType("REAL");
+
+ b.Property("SessionScore")
+ .HasColumnType("INTEGER");
+
+ b.Property("SessionSnapHits")
+ .HasColumnType("INTEGER");
+
+ b.Property("StrainAngleBetween")
+ .HasColumnType("REAL");
+
+ b.Property("TimeSinceLastEvent")
+ .HasColumnType("INTEGER");
+
+ b.Property("WeaponId")
+ .HasColumnType("INTEGER");
+
+ b.Property("When")
+ .HasColumnType("TEXT");
+
+ b.HasKey("SnapshotId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("CurrentViewAngleId");
+
+ b.HasIndex("HitDestinationId");
+
+ b.HasIndex("HitOriginId");
+
+ b.HasIndex("LastStrainAngleId");
+
+ b.ToTable("EFACSnapshot");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b =>
+ {
+ b.Property("ACSnapshotVector3Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("SnapshotId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Vector3Id")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ACSnapshotVector3Id");
+
+ b.HasIndex("SnapshotId");
+
+ b.HasIndex("Vector3Id");
+
+ b.ToTable("EFACSnapshotVector3");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
+ {
+ b.Property("KillId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("AttackerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Damage")
+ .HasColumnType("INTEGER");
+
+ b.Property("DeathOriginVector3Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("DeathType")
+ .HasColumnType("INTEGER");
+
+ b.Property("Fraction")
+ .HasColumnType("REAL");
+
+ b.Property("HitLoc")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsKill")
+ .HasColumnType("INTEGER");
+
+ b.Property("KillOriginVector3Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("Map")
+ .HasColumnType("INTEGER");
+
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("VictimId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ViewAnglesVector3Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("VisibilityPercentage")
+ .HasColumnType("REAL");
+
+ b.Property("Weapon")
+ .HasColumnType("INTEGER");
+
+ b.Property("When")
+ .HasColumnType("TEXT");
+
+ 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("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
+ {
+ b.Property("MessageId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ClientId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Message")
+ .HasColumnType("TEXT");
+
+ b.Property("SentIngame")
+ .HasColumnType("INTEGER");
+
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("TimeSent")
+ .HasColumnType("TEXT");
+
+ b.HasKey("MessageId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("TimeSent");
+
+ b.ToTable("EFClientMessages");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
+ {
+ b.Property("RatingHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ClientId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("RatingHistoryId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("EFClientRatingHistory");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("AverageRecoilOffset")
+ .HasColumnType("REAL");
+
+ b.Property("AverageSnapValue")
+ .HasColumnType("REAL");
+
+ b.Property("Deaths")
+ .HasColumnType("INTEGER");
+
+ b.Property("EloRating")
+ .HasColumnType("REAL");
+
+ b.Property("Kills")
+ .HasColumnType("INTEGER");
+
+ b.Property("MaxStrain")
+ .HasColumnType("REAL");
+
+ b.Property("RollingWeightedKDR")
+ .HasColumnType("REAL");
+
+ b.Property("SPM")
+ .HasColumnType("REAL");
+
+ b.Property("Skill")
+ .HasColumnType("REAL");
+
+ b.Property("SnapHitCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("TimePlayed")
+ .HasColumnType("INTEGER");
+
+ b.Property("VisionAverage")
+ .HasColumnType("REAL");
+
+ b.HasKey("ClientId", "ServerId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFClientStatistics");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
+ {
+ b.Property("HitLocationCountId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("EFClientStatisticsClientId")
+ .HasColumnName("EFClientStatisticsClientId")
+ .HasColumnType("INTEGER");
+
+ b.Property("EFClientStatisticsServerId")
+ .HasColumnName("EFClientStatisticsServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitOffsetAverage")
+ .HasColumnType("REAL");
+
+ b.Property("Location")
+ .HasColumnType("INTEGER");
+
+ b.Property("MaxAngleDistance")
+ .HasColumnType("REAL");
+
+ b.HasKey("HitLocationCountId");
+
+ b.HasIndex("EFClientStatisticsServerId");
+
+ b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId");
+
+ b.ToTable("EFHitLocationCounts");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
+ {
+ b.Property("RatingId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ActivityAmount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Newest")
+ .HasColumnType("INTEGER");
+
+ b.Property("Performance")
+ .HasColumnType("REAL");
+
+ b.Property("Ranking")
+ .HasColumnType("INTEGER");
+
+ b.Property("RatingHistoryId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("When")
+ .HasColumnType("TEXT");
+
+ 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("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
+ {
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("EndPoint")
+ .HasColumnType("TEXT");
+
+ b.Property("GameName")
+ .HasColumnType("INTEGER");
+
+ b.Property("HostName")
+ .HasColumnType("TEXT");
+
+ b.Property("IsPasswordProtected")
+ .HasColumnType("INTEGER");
+
+ b.Property("Port")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ServerId");
+
+ b.ToTable("EFServers");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
+ {
+ b.Property("StatisticId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ServerId")
+ .HasColumnType("INTEGER");
+
+ b.Property("TotalKills")
+ .HasColumnType("INTEGER");
+
+ b.Property("TotalPlayTime")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("StatisticId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFServerStatistics");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
+ {
+ b.Property("AliasId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("DateAdded")
+ .HasColumnType("TEXT");
+
+ b.Property("IPAddress")
+ .HasColumnType("INTEGER");
+
+ b.Property("LinkId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasMaxLength(24);
+
+ b.Property("SearchableName")
+ .HasColumnType("TEXT")
+ .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("SharedLibraryCore.Database.Models.EFAliasLink", b =>
+ {
+ b.Property("AliasLinkId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("AliasLinkId");
+
+ b.ToTable("EFAliasLinks");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
+ {
+ b.Property("ChangeHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("Comment")
+ .HasColumnType("TEXT")
+ .HasMaxLength(128);
+
+ b.Property("CurrentValue")
+ .HasColumnType("TEXT");
+
+ b.Property("ImpersonationEntityId")
+ .HasColumnType("INTEGER");
+
+ b.Property("OriginEntityId")
+ .HasColumnType("INTEGER");
+
+ b.Property("PreviousValue")
+ .HasColumnType("TEXT");
+
+ b.Property("TargetEntityId")
+ .HasColumnType("INTEGER");
+
+ b.Property("TimeChanged")
+ .HasColumnType("TEXT");
+
+ b.Property("TypeOfChange")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ChangeHistoryId");
+
+ b.ToTable("EFChangeHistory");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("AliasLinkId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Connections")
+ .HasColumnType("INTEGER");
+
+ b.Property("CurrentAliasId")
+ .HasColumnType("INTEGER");
+
+ b.Property("FirstConnection")
+ .HasColumnType("TEXT");
+
+ b.Property("LastConnection")
+ .HasColumnType("TEXT");
+
+ b.Property("Level")
+ .HasColumnType("INTEGER");
+
+ b.Property("Masked")
+ .HasColumnType("INTEGER");
+
+ b.Property("NetworkId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Password")
+ .HasColumnType("TEXT");
+
+ b.Property("PasswordSalt")
+ .HasColumnType("TEXT");
+
+ b.Property("TotalConnectionTime")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ClientId");
+
+ b.HasIndex("AliasLinkId");
+
+ b.HasIndex("CurrentAliasId");
+
+ b.HasIndex("NetworkId")
+ .IsUnique();
+
+ b.ToTable("EFClients");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
+ {
+ b.Property("MetaId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("ClientId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("Extra")
+ .HasColumnType("TEXT");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasMaxLength(32);
+
+ b.Property("Updated")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("MetaId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("Key");
+
+ b.ToTable("EFMeta");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
+ {
+ b.Property("PenaltyId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Active")
+ .HasColumnType("INTEGER");
+
+ b.Property("AutomatedOffense")
+ .HasColumnType("TEXT");
+
+ b.Property("Expires")
+ .HasColumnType("TEXT");
+
+ b.Property("IsEvadedOffense")
+ .HasColumnType("INTEGER");
+
+ b.Property("LinkId")
+ .HasColumnType("INTEGER");
+
+ b.Property("OffenderId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Offense")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("PunisherId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.Property("When")
+ .HasColumnType("TEXT");
+
+ b.HasKey("PenaltyId");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("OffenderId");
+
+ b.HasIndex("PunisherId");
+
+ b.ToTable("EFPenalties");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
+ {
+ b.Property("Vector3Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("X")
+ .HasColumnType("REAL");
+
+ b.Property("Y")
+ .HasColumnType("REAL");
+
+ b.Property("Z")
+ .HasColumnType("REAL");
+
+ b.HasKey("Vector3Id");
+
+ b.ToTable("Vector3");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
+ .WithMany()
+ .HasForeignKey("CurrentViewAngleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
+ .WithMany()
+ .HasForeignKey("HitDestinationId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
+ .WithMany()
+ .HasForeignKey("HitOriginId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
+ .WithMany()
+ .HasForeignKey("LastStrainAngleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot")
+ .WithMany("PredictedViewAngles")
+ .HasForeignKey("SnapshotId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector")
+ .WithMany()
+ .HasForeignKey("Vector3Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
+ .WithMany()
+ .HasForeignKey("AttackerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
+ .WithMany()
+ .HasForeignKey("DeathOriginVector3Id");
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
+ .WithMany()
+ .HasForeignKey("KillOriginVector3Id");
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
+ .WithMany()
+ .HasForeignKey("VictimId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
+ .WithMany()
+ .HasForeignKey("ViewAnglesVector3Id");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("EFClientStatisticsClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("EFClientStatisticsServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null)
+ .WithMany("HitLocations")
+ .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
+ .WithMany("Ratings")
+ .HasForeignKey("RatingHistoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
+ .WithMany("Children")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
+ .WithMany()
+ .HasForeignKey("AliasLinkId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
+ .WithMany()
+ .HasForeignKey("CurrentAliasId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany("Meta")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("OffenderId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
+ .WithMany("AdministeredPenalties")
+ .HasForeignKey("PunisherId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs
new file mode 100644
index 000000000..42ccaf6ef
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs
@@ -0,0 +1,23 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace SharedLibraryCore.Migrations
+{
+ public partial class AddSentIngameFlagToClientMessage : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "SentIngame",
+ table: "EFClientMessages",
+ nullable: false,
+ defaultValue: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "SentIngame",
+ table: "EFClientMessages");
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
index 4a6d3f7f8..e4371a055 100644
--- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
+++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
@@ -222,6 +222,9 @@ namespace SharedLibraryCore.Migrations
b.Property("Message")
.HasColumnType("TEXT");
+ b.Property("SentIngame")
+ .HasColumnType("INTEGER");
+
b.Property("ServerId")
.HasColumnType("INTEGER");
diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj
index 421860292..d70dcf2f9 100644
--- a/SharedLibraryCore/SharedLibraryCore.csproj
+++ b/SharedLibraryCore/SharedLibraryCore.csproj
@@ -4,7 +4,7 @@
Library
netcoreapp3.1
RaidMax.IW4MAdmin.SharedLibraryCore
- 2.4.10
+ 2020.11.18.1
RaidMax
Forever None
Debug;Release;Prerelease
@@ -19,9 +19,7 @@
true
MIT
Shared Library for IW4MAdmin
- 2020.11.11.1
- 2020.11.11.1
- 2020.11.11.1
+ 2020.11.18.1
diff --git a/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml b/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml
index b5d2f9c1b..0302d75c4 100644
--- a/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml
+++ b/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml
@@ -3,7 +3,12 @@
-
+
+ @if (!Model.SentIngame)
+ {
+ [@ViewBag.Localization["WEBFRONT_PROFILE_MESSAGE_EXTERNAL"]]
+ }
+
@if (Model.IsHidden && !ViewBag.Authorized)
{
diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj
index b3e416e1f..fb51fa631 100644
--- a/WebfrontCore/WebfrontCore.csproj
+++ b/WebfrontCore/WebfrontCore.csproj
@@ -40,6 +40,7 @@
+
@@ -51,6 +52,7 @@
+
@@ -93,6 +95,14 @@
+
+
+
+
+
+
+
+