diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 5398b481c..a58f026f0 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -300,6 +300,13 @@ namespace IW4MAdmin Time = DateTime.UtcNow }); + var clientTag = await _metaService.GetPersistentMeta(EFMeta.ClientTag, E.Origin); + + if (clientTag?.LinkedMeta != null) + { + E.Origin.Tag = clientTag.LinkedMeta.Value; + } + await E.Origin.OnJoin(E.Origin.IPAddress); } } diff --git a/Application/Main.cs b/Application/Main.cs index 3460dfc7d..c09159adb 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -186,7 +186,7 @@ namespace IW4MAdmin.Application await Task.WhenAll(tasks); logger.LogInformation("Shutdown completed successfully"); - Console.Write(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); } @@ -318,6 +318,15 @@ namespace IW4MAdmin.Application appConfigHandler.Set(appConfig); appConfigHandler.Save(); } + + // register override level names + foreach (var (key, value) in appConfig.OverridePermissionLevelNames) + { + if (!Utilities.PermissionLevelOverrides.ContainsKey(key)) + { + Utilities.PermissionLevelOverrides.Add(key, value); + } + } // build the dependency list HandlePluginRegistration(appConfig, serviceCollection, masterRestClient); diff --git a/Application/Misc/MetaService.cs b/Application/Misc/MetaService.cs index fcf0cd48b..7de83bf23 100644 --- a/Application/Misc/MetaService.cs +++ b/Application/Misc/MetaService.cs @@ -29,7 +29,7 @@ namespace IW4MAdmin.Application.Misc _contextFactory = contextFactory; } - public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client) + public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client, EFMeta linkedMeta = null) { // this seems to happen if the client disconnects before they've had time to authenticate and be added if (client.ClientId < 1) @@ -48,6 +48,7 @@ namespace IW4MAdmin.Application.Misc { existingMeta.Value = metaValue; existingMeta.Updated = DateTime.UtcNow; + existingMeta.LinkedMetaId = linkedMeta?.MetaId; } else @@ -57,13 +58,98 @@ namespace IW4MAdmin.Application.Misc ClientId = client.ClientId, Created = DateTime.UtcNow, Key = metaKey, - Value = metaValue + Value = metaValue, + LinkedMetaId = linkedMeta?.MetaId }); } await ctx.SaveChangesAsync(); } + public async Task AddPersistentMeta(string metaKey, string metaValue) + { + await using var ctx = _contextFactory.CreateContext(); + + var existingMeta = await ctx.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .ToListAsync(); + + var matchValues = existingMeta + .Where(meta => meta.Value == metaValue) + .ToArray(); + + if (matchValues.Any()) + { + foreach (var meta in matchValues) + { + _logger.LogDebug("Updating existing meta with key {key} and id {id}", meta.Key, meta.MetaId); + meta.Value = metaValue; + meta.Updated = DateTime.UtcNow; + } + + await ctx.SaveChangesAsync(); + } + + else + { + _logger.LogDebug("Adding new meta with key {key}", metaKey); + + ctx.EFMeta.Add(new EFMeta() + { + Created = DateTime.UtcNow, + Key = metaKey, + Value = metaValue + }); + + await ctx.SaveChangesAsync(); + } + } + + public async Task RemovePersistentMeta(string metaKey, EFClient client) + { + await using var context = _contextFactory.CreateContext(); + + var existingMeta = await context.EFMeta + .FirstOrDefaultAsync(meta => meta.Key == metaKey && meta.ClientId == client.ClientId); + + if (existingMeta == null) + { + _logger.LogDebug("No meta with key {key} found for client id {id}", metaKey, client.ClientId); + return; + } + + _logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, existingMeta.MetaId); + context.EFMeta.Remove(existingMeta); + await context.SaveChangesAsync(); + } + + public async Task RemovePersistentMeta(string metaKey, string metaValue = null) + { + await using var context = _contextFactory.CreateContext(enableTracking: false); + var existingMeta = await context.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .ToListAsync(); + + if (metaValue == null) + { + _logger.LogDebug("Removing all meta for key {key} with ids [{ids}] ", metaKey, string.Join(", ", existingMeta.Select(meta => meta.MetaId))); + existingMeta.ForEach(meta => context.Remove(existingMeta)); + await context.SaveChangesAsync(); + return; + } + + var foundMeta = existingMeta.FirstOrDefault(meta => meta.Value == metaValue); + + if (foundMeta != null) + { + _logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, foundMeta.MetaId); + context.Remove(foundMeta); + await context.SaveChangesAsync(); + } + } + public async Task GetPersistentMeta(string metaKey, EFClient client) { await using var ctx = _contextFactory.CreateContext(enableTracking: false); @@ -76,11 +162,34 @@ namespace IW4MAdmin.Application.Misc MetaId = _meta.MetaId, Key = _meta.Key, ClientId = _meta.ClientId, - Value = _meta.Value + Value = _meta.Value, + LinkedMetaId = _meta.LinkedMetaId, + LinkedMeta = _meta.LinkedMetaId != null ? new EFMeta() + { + MetaId = _meta.LinkedMeta.MetaId, + Key = _meta.LinkedMeta.Key, + Value = _meta.LinkedMeta.Value + } : null }) .FirstOrDefaultAsync(); } + public async Task> GetPersistentMeta(string metaKey) + { + await using var context = _contextFactory.CreateContext(enableTracking: false); + return await context.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .Select(meta => new EFMeta + { + MetaId = meta.MetaId, + Key = meta.Key, + ClientId = meta.ClientId, + Value = meta.Value, + }) + .ToListAsync(); + } + public void AddRuntimeMeta(MetaType metaKey, Func>> metaAction) where T : PaginationRequest where V : IClientMeta { if (!_metaActions.ContainsKey(metaKey)) diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index 00716d9ce..5d19ac1de 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -13,51 +13,12 @@ using System.Net; using Newtonsoft.Json.Linq; using System.Text.RegularExpressions; using static SharedLibraryCore.Database.Models.EFClient; +using Humanizer; namespace IW4MAdmin.Plugins.Welcome { public class Plugin : IPlugin { - String TimesConnected(EFClient P) - { - int connection = P.Connections; - String Prefix = String.Empty; - if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19)) - Prefix = "th"; - else - { - switch (connection % 10) - { - case 1: - Prefix = "st"; - break; - case 2: - Prefix = "nd"; - break; - case 3: - Prefix = "rd"; - break; - } - } - - switch (connection) - { - case 0: - case 1: - return "first"; - case 2: - return "second"; - case 3: - return "third"; - case 4: - return "fourth"; - case 5: - return "fifth"; - default: - return connection.ToString() + Prefix; - } - } - public string Author => "RaidMax"; public float Version => 1.0f; @@ -91,7 +52,7 @@ namespace IW4MAdmin.Plugins.Welcome if (E.Type == GameEvent.EventType.Join) { EFClient newPlayer = E.Origin; - if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked) + if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked || !string.IsNullOrEmpty(newPlayer.GetAdditionalProperty("ClientTag"))) E.Owner.Broadcast(await ProcessAnnouncement(_configHandler.Configuration().PrivilegedAnnouncementMessage, newPlayer)); newPlayer.Tell(await ProcessAnnouncement(_configHandler.Configuration().UserWelcomeMessage, newPlayer)); @@ -119,13 +80,13 @@ namespace IW4MAdmin.Plugins.Welcome private async Task ProcessAnnouncement(string msg, EFClient joining) { msg = msg.Replace("{{ClientName}}", joining.Name); - msg = msg.Replace("{{ClientLevel}}", Utilities.ConvertLevelToColor(joining.Level, joining.ClientPermission.Name)); + msg = msg.Replace("{{ClientLevel}}", $"{Utilities.ConvertLevelToColor(joining.Level, joining.ClientPermission.Name)}{(string.IsNullOrEmpty(joining.GetAdditionalProperty("ClientTag")) ? "" : $" ^7({joining.GetAdditionalProperty("ClientTag")}^7)")}"); // this prevents it from trying to evaluate it every message if (msg.Contains("{{ClientLocation}}")) { msg = msg.Replace("{{ClientLocation}}", await GetCountryName(joining.IPAddressString)); } - msg = msg.Replace("{{TimesConnected}}", TimesConnected(joining)); + msg = msg.Replace("{{TimesConnected}}", joining.Connections.Ordinalize()); return msg; } diff --git a/SharedLibraryCore/Command.cs b/SharedLibraryCore/Command.cs index 5a8b788de..7f61bd112 100644 --- a/SharedLibraryCore/Command.cs +++ b/SharedLibraryCore/Command.cs @@ -28,9 +28,9 @@ namespace SharedLibraryCore /// /// Executes the command /// - /// + /// /// - abstract public Task ExecuteAsync(GameEvent E); + abstract public Task ExecuteAsync(GameEvent gameEvent); /// /// Specifies the name and string that triggers the command diff --git a/SharedLibraryCore/Commands/AddClientTagCommand.cs b/SharedLibraryCore/Commands/AddClientTagCommand.cs new file mode 100644 index 000000000..c696f5ade --- /dev/null +++ b/SharedLibraryCore/Commands/AddClientTagCommand.cs @@ -0,0 +1,37 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class AddClientTagCommand : Command + { + private readonly IMetaService _metaService; + + public AddClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "addclienttag"; + Description = layout["COMMANDS_ADD_CLIENT_TAG_DESC"]; + Alias = "act"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + await _metaService.AddPersistentMeta(EFMeta.ClientTagName, gameEvent.Data); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_ADD_CLIENT_TAG_SUCCESS"].FormatExt(gameEvent.Data)); + } + } +} diff --git a/SharedLibraryCore/Commands/ListClientTags.cs b/SharedLibraryCore/Commands/ListClientTags.cs new file mode 100644 index 000000000..ef1f23f19 --- /dev/null +++ b/SharedLibraryCore/Commands/ListClientTags.cs @@ -0,0 +1,33 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + + public class ListClientTags : Command + { + private readonly IMetaService _metaService; + + public ListClientTags(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "listclienttags"; + Description = layout["COMMANDS_LIST_CLIENT_TAGS_DESC"]; + Alias = "lct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + var tags = await _metaService.GetPersistentMeta(EFMeta.ClientTagName); + gameEvent.Origin.Tell(tags.Select(tag => tag.Value)); + } + } +} diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 3926f83bf..abd659b6f 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -465,10 +465,11 @@ namespace SharedLibraryCore.Commands RequiresTarget = false; } - public override Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent gameEvent) { - string you = string.Format("{0} [^3#{1}^7] {2} ^7[^3@{3}^7] ^7[{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level, E.Origin.ClientPermission.Name), E.Origin.IPAddressString); - E.Origin.Tell(you); + var you = _translationLookup["COMMANDS_WHOAMI_FORMAT"].FormatExt(gameEvent.Origin.ClientNumber, gameEvent.Origin.ClientId, gameEvent.Origin.GuidString, + gameEvent.Origin.IPAddressString, gameEvent.Origin.ClientPermission.Name, string.IsNullOrEmpty(gameEvent.Origin.Tag) ? "" : $" {gameEvent.Origin.Tag}^7", gameEvent.Origin.Name); + gameEvent.Origin.Tell(you); return Task.CompletedTask; } @@ -488,46 +489,14 @@ namespace SharedLibraryCore.Commands RequiresTarget = false; } - public override Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent gameEvent) { - StringBuilder playerList = new StringBuilder(); - int count = 0; - for (int i = 0; i < E.Owner.Clients.Count; i++) - { - var P = E.Owner.Clients[i]; + var clientList = gameEvent.Owner.GetClientsAsList() + .Select(client => _translationLookup["COMMANDS_LIST_FORMAT"] + .FormatExt(client.ClientPermission.Name, string.IsNullOrEmpty(client.Tag) ? "" : $" {client.Tag}^7", client.ClientNumber, client.Name)) + .ToArray(); - if (P == null) - { - continue; - } - // todo: fix spacing - // todo: make this better :) - if (P.Masked) - { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(EFClient.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - EFClient.Permission.User.ToString().Length)); - } - else - { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); - } - - if (count == 2 || E.Owner.GetClientsAsList().Count == 1) - { - E.Origin.Tell(playerList.ToString()); - count = 0; - playerList = new StringBuilder(); - continue; - } - - count++; - } - - if (playerList.Length > 0) - { - E.Origin.Tell(playerList.ToString()); - } - - // todo: make no players response for webfront + gameEvent.Origin.Tell(clientList); return Task.CompletedTask; } @@ -737,7 +706,7 @@ namespace SharedLibraryCore.Commands { // can't promote a client to higher than your current perms // or your peer - gameEvent.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToString())); + gameEvent.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToLocalizedLevelName())); return; } @@ -991,9 +960,14 @@ namespace SharedLibraryCore.Commands rules.AddRange(E.Owner.ServerConfig.Rules); } - foreach (string r in rules) + var ruleFomat = rules.Select(r => $"- {r}"); + if (E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { - var _ = E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix) ? E.Owner.Broadcast($"- {r}") : E.Origin.Tell($"- {r}"); + E.Owner.Broadcast(ruleFomat); + } + else + { + E.Origin.Tell(ruleFomat); } } diff --git a/SharedLibraryCore/Commands/RemoveClientTagCommand.cs b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs new file mode 100644 index 000000000..10c529109 --- /dev/null +++ b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs @@ -0,0 +1,37 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class RemoveClientTag : Command + { + private readonly IMetaService _metaService; + + public RemoveClientTag(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "removeclienttag"; + Description = layout["COMMANDS_REMOVE_CLIENT_TAG_DESC"]; + Alias = "rct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + await _metaService.RemovePersistentMeta(EFMeta.ClientTagName, gameEvent.Data); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_REMOVE_CLIENT_TAG_SUCCESS"].FormatExt(gameEvent.Data)); + } + } +} diff --git a/SharedLibraryCore/Commands/SetClientTagCommand.cs b/SharedLibraryCore/Commands/SetClientTagCommand.cs new file mode 100644 index 000000000..c0952c8a1 --- /dev/null +++ b/SharedLibraryCore/Commands/SetClientTagCommand.cs @@ -0,0 +1,49 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class SetClientTagCommand : Command + { + private readonly IMetaService _metaService; + + + public SetClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "setclienttag"; + Description = layout["COMMANDS_SET_CLIENT_TAG_DESC"]; + Alias = "sct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + var availableTags = await _metaService.GetPersistentMeta(EFMeta.ClientTagName); + var matchingTag = availableTags.FirstOrDefault(tag => tag.Value == gameEvent.Data); + + if (matchingTag == null) + { + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SET_CLIENT_TAG_FAIL"].FormatExt(gameEvent.Data)); + return; + } + + gameEvent.Target.Tag = matchingTag.Value; + await _metaService.AddPersistentMeta(EFMeta.ClientTag, string.Empty, gameEvent.Target, matchingTag); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SET_CLIENT_TAG_SUCCESS"].FormatExt(matchingTag.Value)); + } + } +} diff --git a/SharedLibraryCore/Commands/UnsetClientTagCommand.cs b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs new file mode 100644 index 000000000..4dbd2a1c7 --- /dev/null +++ b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs @@ -0,0 +1,40 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class UnsetClientTagCommand : Command + { + private readonly IMetaService _metaService; + + + public UnsetClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "unsetclienttag"; + Description = layout["COMMANDS_UNSET_CLIENT_TAG_DESC"]; + Alias = "uct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + gameEvent.Target.Tag = null; + await _metaService.RemovePersistentMeta(EFMeta.ClientTag, gameEvent.Target); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_UNSET_CLIENT_TAG_SUCCESS"]); + } + } +} diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index f74ee0e6e..3ec1ad803 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -3,6 +3,8 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Linq; +using static SharedLibraryCore.Database.Models.EFClient; namespace SharedLibraryCore.Configuration { @@ -137,6 +139,10 @@ namespace SharedLibraryCore.Configuration {{"afk", "Away from keyboard"}, {"ci", "Connection interrupted. Reconnect"}}; [LocalizedDisplayName(("WEBFRONT_CONFIGURATION_ENABLE_PRIVILEGED_USER_PRIVACY"))] public bool EnablePrivilegedUserPrivacy { get; set; } + public Dictionary OverridePermissionLevelNames { get; set; } = Enum + .GetValues(typeof(Permission)) + .Cast() + .ToDictionary(perm => perm, perm => perm.ToString()); [UIHint("ServerConfiguration")] public ServerConfiguration[] Servers { get; set; } diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs index 354919df0..c7e7a9203 100644 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ b/SharedLibraryCore/Database/DatabaseContext.cs @@ -57,12 +57,12 @@ namespace SharedLibraryCore.Database public DatabaseContext(DbContextOptions options) : base(options) { - + } protected DatabaseContext(DbContextOptions options) : base(options) { - + } public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) @@ -123,6 +123,10 @@ namespace SharedLibraryCore.Database modelBuilder.Entity(ent => { ent.HasIndex(_meta => _meta.Key); + ent.HasIndex(_meta => _meta.LinkedMetaId); + ent.HasOne(_meta => _meta.LinkedMeta) + .WithMany() + .OnDelete(DeleteBehavior.SetNull); }); // force full name for database conversion diff --git a/SharedLibraryCore/Database/Models/EFMeta.cs b/SharedLibraryCore/Database/Models/EFMeta.cs index 3525fb286..792797ee4 100644 --- a/SharedLibraryCore/Database/Models/EFMeta.cs +++ b/SharedLibraryCore/Database/Models/EFMeta.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Text; namespace SharedLibraryCore.Database.Models { @@ -11,15 +9,18 @@ namespace SharedLibraryCore.Database.Models /// public class EFMeta : SharedEntity { + public const string ClientTagName = nameof(ClientTagName); + public const string ClientTag = nameof(ClientTag); + [Key] public int MetaId { get; set; } [Required] public DateTime Created { get; set; } = DateTime.UtcNow; [Required] public DateTime Updated { get; set; } = DateTime.UtcNow; - [Required] - public int ClientId { get; set; } - [ForeignKey("ClientId")] // this is the client that the meta belongs to + public int? ClientId { get; set; } + // this is the client that the meta could belong to + [ForeignKey(nameof(ClientId))] public virtual EFClient Client { get; set; } [Required] [MinLength(3)] @@ -29,5 +30,9 @@ namespace SharedLibraryCore.Database.Models [Required] public string Value { get; set; } public string Extra { get; set; } + + public int? LinkedMetaId { get; set; } + [ForeignKey(nameof(LinkedMetaId))] + public virtual EFMeta LinkedMeta { get; set; } } } diff --git a/SharedLibraryCore/Dtos/PlayerInfo.cs b/SharedLibraryCore/Dtos/PlayerInfo.cs index 94b91561e..eecaa6154 100644 --- a/SharedLibraryCore/Dtos/PlayerInfo.cs +++ b/SharedLibraryCore/Dtos/PlayerInfo.cs @@ -11,6 +11,7 @@ namespace SharedLibraryCore.Dtos public string Name { get; set; } public int ClientId { get; set; } public string Level { get; set; } + public string Tag { get; set; } public int LevelInt { get; set; } public string IPAddress { get; set; } public long NetworkId { get; set; } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index d814ea9b8..974617b5f 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -261,6 +261,11 @@ namespace SharedLibraryCore _eventFinishedWaiter.Set(); } + public async Task WaitAsync() + { + return await WaitAsync(Utilities.DefaultCommandTimeout, new CancellationToken()); + } + /// /// asynchronously wait for GameEvent to be processed /// diff --git a/SharedLibraryCore/Interfaces/IMetaService.cs b/SharedLibraryCore/Interfaces/IMetaService.cs index 71e0ec23a..42c06c8bb 100644 --- a/SharedLibraryCore/Interfaces/IMetaService.cs +++ b/SharedLibraryCore/Interfaces/IMetaService.cs @@ -16,7 +16,31 @@ namespace SharedLibraryCore.Interfaces /// value of the meta data /// client to save the meta for /// - Task AddPersistentMeta(string metaKey, string metaValue, EFClient client); + Task AddPersistentMeta(string metaKey, string metaValue, EFClient client, EFMeta linkedMeta = null); + + /// + /// adds or updates meta key and value to the database + /// + /// key of meta data + /// value of the meta data + /// + Task AddPersistentMeta(string metaKey, string metaValue); + + /// + /// removes meta key with given value + /// + /// key of meta data + /// client to delete the meta for + /// + Task RemovePersistentMeta(string metaKey, EFClient client); + + /// + /// removes meta key with given value + /// + /// key of the meta data + /// value of the meta data + /// + Task RemovePersistentMeta(string metaKey, string metaValue = null); /// /// retrieves meta data for given client and key @@ -26,6 +50,13 @@ namespace SharedLibraryCore.Interfaces /// Task GetPersistentMeta(string metaKey, EFClient client); + /// + /// retrieves collection of meta for given key + /// + /// key to retrieve values for + /// + Task> GetPersistentMeta(string metaKey); + /// /// adds a meta task to the runtime meta list /// diff --git a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs new file mode 100644 index 000000000..933e63984 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -0,0 +1,929 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20210123023921_UpdateEFMetaToSupportNonClientMeta")] + partial class UpdateEFMetaToSupportNonClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + 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("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("SharedLibraryCore.Database.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("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.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("SharedLibraryCore.Database.Models.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("SharedLibraryCore.Database.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("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.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("SharedLibraryCore.Helpers.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("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"); + }); + + 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/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs new file mode 100644 index 000000000..1a748afd4 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.MySql +{ + public partial class UpdateEFMetaToSupportNonClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "int", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs new file mode 100644 index 000000000..745b1b34a --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -0,0 +1,939 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20210124170830_UpdateEFMetaToSupportLinkedMeta")] + partial class UpdateEFMetaToSupportLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + 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("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("IW4MAdmin.Plugins.Stats.Models.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("SharedLibraryCore.Database.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("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.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("SharedLibraryCore.Database.Models.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("SharedLibraryCore.Database.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("SharedLibraryCore.Database.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("SharedLibraryCore.Helpers.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("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"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + 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/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs new file mode 100644 index 000000000..30e37b9b4 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.MySql +{ + public partial class UpdateEFMetaToSupportLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LinkedMetaId", + table: "EFMeta", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId", + principalTable: "EFMeta", + principalColumn: "MetaId", + onDelete: ReferentialAction.SetNull); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropColumn( + name: "LinkedMetaId", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs index 49d3de31f..933b9b726 100644 --- a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations.MySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => @@ -470,11 +470,11 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("Name") .IsRequired() - .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") .HasMaxLength(24); b.Property("SearchableName") - .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") .HasMaxLength(24); b.HasKey("AliasId"); @@ -609,7 +609,7 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("Active") .HasColumnType("tinyint(1)"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("int"); b.Property("Created") @@ -623,6 +623,9 @@ namespace SharedLibraryCore.Migrations.MySql .HasColumnType("varchar(32) CHARACTER SET utf8mb4") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("int"); + b.Property("Updated") .HasColumnType("datetime(6)"); @@ -636,6 +639,8 @@ namespace SharedLibraryCore.Migrations.MySql b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -898,9 +903,12 @@ namespace SharedLibraryCore.Migrations.MySql { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs new file mode 100644 index 000000000..cfb4d9e8d --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -0,0 +1,946 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20210123024304_UpdateEFMetaToSupportNonClientMeta")] + partial class UpdateEFMetaToSupportNonClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + 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("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .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("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + 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("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + 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"); + }); + + 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/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs new file mode 100644 index 000000000..fc4f4aa30 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateEFMetaToSupportNonClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "integer", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs new file mode 100644 index 000000000..cd28418d2 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -0,0 +1,956 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20210124170956_UpdateEFMetaToSupportLinkedMeta")] + partial class UpdateEFMetaToSupportLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + 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("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .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("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("integer"); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + 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("timestamp without time zone"); + + 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") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + 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"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + 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/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs new file mode 100644 index 000000000..55927c720 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateEFMetaToSupportLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LinkedMetaId", + table: "EFMeta", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId", + principalTable: "EFMeta", + principalColumn: "MetaId", + onDelete: ReferentialAction.SetNull); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropColumn( + name: "LinkedMetaId", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs index 5917c4448..0d4427530 100644 --- a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs @@ -15,8 +15,8 @@ namespace SharedLibraryCore.Migrations.Postgresql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 63); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => @@ -24,7 +24,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("SnapshotId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -121,7 +121,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ACSnapshotVector3Id") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -146,7 +146,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("KillId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -218,7 +218,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("MessageId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -254,7 +254,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("RatingHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -328,7 +328,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("HitLocationCountId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -367,7 +367,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("RatingId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -439,7 +439,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("StatisticId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -465,7 +465,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("AliasId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -509,7 +509,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("AliasLinkId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -524,7 +524,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ChangeHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -564,7 +564,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ClientId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -619,12 +619,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("MetaId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("integer"); b.Property("Created") @@ -638,6 +638,9 @@ namespace SharedLibraryCore.Migrations.Postgresql .HasColumnType("character varying(32)") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("integer"); + b.Property("Updated") .HasColumnType("timestamp without time zone"); @@ -651,6 +654,8 @@ namespace SharedLibraryCore.Migrations.Postgresql b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -659,7 +664,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("PenaltyId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -708,7 +713,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("Vector3Id") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("X") .HasColumnType("real"); @@ -915,9 +920,12 @@ namespace SharedLibraryCore.Migrations.Postgresql { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs new file mode 100644 index 000000000..8966c2d4c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs @@ -0,0 +1,938 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta")] + partial class UpdateEFMetaToSupportNonClientMetaAndLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10"); + + 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("LinkedMetaId") + .HasColumnType("INTEGER"); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + 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"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + 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/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs new file mode 100644 index 000000000..5137722e9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs @@ -0,0 +1,128 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class UpdateEFMetaToSupportNonClientMetaAndLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFMeta; + + DROP TABLE EFMeta; + + CREATE TABLE EFMeta ( + MetaId INTEGER NOT NULL + CONSTRAINT PK_EFMeta PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + ClientId INTEGER, + Created TEXT NOT NULL, + Extra TEXT, + [Key] TEXT NOT NULL, + Updated TEXT NOT NULL, + Value TEXT NOT NULL, + LinkedMetaId INTEGER CONSTRAINT IX_EFMeta_LinkedMetaId REFERENCES EFMeta (MetaId) ON DELETE SET NULL, + CONSTRAINT FK_EFMeta_EFClients_ClientId FOREIGN KEY ( + ClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE + ); + + INSERT INTO EFMeta ( + MetaId, + Active, + ClientId, + Created, + Extra, + [Key], + Updated, + Value + ) + SELECT MetaId, + Active, + ClientId, + Created, + Extra, + ""Key"", + Updated, + Value + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFMeta_ClientId ON EFMeta( + ""ClientId"" + ); + + CREATE INDEX IX_EFMeta_Key ON EFMeta ( + ""Key"" + ); + + CREATE INDEX IX_EFMeta_LinkedMetaId ON EFMeta ( + LinkedMetaId + ); + + PRAGMA foreign_keys = 1;"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFMeta; + + DROP TABLE EFMeta; + + CREATE TABLE EFMeta ( + MetaId INTEGER NOT NULL + CONSTRAINT PK_EFMeta PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + ClientId INTEGER NOT NULL, + Created TEXT NOT NULL, + Extra TEXT, + [Key] TEXT NOT NULL, + Updated TEXT NOT NULL, + Value TEXT NOT NULL, + CONSTRAINT FK_EFMeta_EFClients_ClientId FOREIGN KEY ( + ClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE + ); + + INSERT INTO EFMeta ( + MetaId, + Active, + ClientId, + Created, + Extra, + [Key], + Updated, + Value + ) + SELECT MetaId, + Active, + ClientId, + Created, + Extra, + ""Key"", + Updated, + Value + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFMeta_ClientId ON EFMeta( + ""ClientId"" + ); + + CREATE INDEX IX_EFMeta_Key ON EFMeta( + ""Key"" + ); + + PRAGMA foreign_keys = 1;"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index e84556910..90f555e4e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations.Sqlite { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.7"); + .HasAnnotation("ProductVersion", "3.1.10"); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => { @@ -608,7 +608,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.Property("Active") .HasColumnType("INTEGER"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Created") @@ -622,6 +622,9 @@ namespace SharedLibraryCore.Migrations.Sqlite .HasColumnType("TEXT") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + b.Property("Updated") .HasColumnType("TEXT"); @@ -635,6 +638,8 @@ namespace SharedLibraryCore.Migrations.Sqlite b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -897,9 +902,12 @@ namespace SharedLibraryCore.Migrations.Sqlite { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index 25b73f59d..b0789462a 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -152,6 +152,16 @@ namespace SharedLibraryCore.Database.Models return e; } + public void Tell(IEnumerable messages) + { + foreach(var message in messages) + { +#pragma warning disable 4014 + Tell(message).WaitAsync(); +#pragma warning restore 4014 + } + } + /// /// warn a client with given reason /// @@ -706,10 +716,16 @@ namespace SharedLibraryCore.Database.Models public ClientPermission ClientPermission => new ClientPermission() { Level = Level, - Name = Utilities.CurrentLocalization - .LocalizationIndex[$"GLOBAL_PERMISSION_{Level.ToString().ToUpper()}"] + Name = Level.ToLocalizedLevelName() }; + [NotMapped] + public string Tag + { + get => GetAdditionalProperty(EFMeta.ClientTag); + set => SetAdditionalProperty(EFMeta.ClientTag, value); + } + [NotMapped] private readonly SemaphoreSlim _processingEvent; diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 5449d8285..f13e12390 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -140,6 +140,17 @@ namespace SharedLibraryCore Manager.AddEvent(e); return e; } + + public void Broadcast(IEnumerable messages, EFClient sender = null) + { + foreach (var message in messages) + { +#pragma warning disable 4014 + Broadcast(message, sender).WaitAsync(); +#pragma warning restore 4014 + } + } + /// /// Send a message to a particular players diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 35d7baec4..8bbcf55bf 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -59,6 +59,12 @@ + + + + + + diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index ab30705e6..a3c2c7856 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -59,6 +59,7 @@ namespace SharedLibraryCore /// fallback id for world events /// public const long WORLD_ID = -1; + public static Dictionary PermissionLevelOverrides { get; } = new Dictionary(); public static string HttpRequest(string location, string header, string headerValue) { @@ -219,9 +220,12 @@ namespace SharedLibraryCore return $"^{colorCode}{localizedLevel ?? level.ToString()}"; } - public static string ToLocalizedLevelName(this EFClient.Permission perm) + public static string ToLocalizedLevelName(this Permission permission) { - return CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"]; + var localized = CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{permission.ToString().ToUpper()}"]; + return PermissionLevelOverrides.ContainsKey(permission) && PermissionLevelOverrides[permission] != localized + ? PermissionLevelOverrides[permission] + : localized; } public async static Task ProcessMessageToken(this Server server, IList tokens, String str) diff --git a/WebfrontCore/Controllers/API/ClientController.cs b/WebfrontCore/Controllers/API/ClientController.cs index 90bb610b0..14a8eca75 100644 --- a/WebfrontCore/Controllers/API/ClientController.cs +++ b/WebfrontCore/Controllers/API/ClientController.cs @@ -88,8 +88,6 @@ namespace WebfrontCore.Controllers.API return Unauthorized(); } - HttpContext.Request.Cookies.TryGetValue(".AspNetCore.Cookies", out var cookie); - if (Authorized) { return Ok(); diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index aadd4f313..774c1a3ea 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -439,7 +439,7 @@ namespace WebfrontCore.Controllers private Dictionary GetPresetPenaltyReasons() => _appConfig.PresetPenaltyReasons.Values .Concat(_appConfig.GlobalRules) - .Concat(_appConfig.Servers.SelectMany(server => server.Rules)) + .Concat(_appConfig.Servers.SelectMany(server => server.Rules ?? new string[0])) .Distinct() .Select((value, index) => new { diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index 547d3b7af..86a7e353c 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -36,6 +36,11 @@ namespace WebfrontCore.Controllers var activePenalties = (await Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId, client.IPAddress)); + var tag = await _metaService.GetPersistentMeta(EFMeta.ClientTag, client); + if (tag?.LinkedMeta != null) + { + client.SetAdditionalProperty(EFMeta.ClientTag, tag.LinkedMeta.Value); + } int displayLevelInt = (int)client.Level; string displayLevel = client.Level.ToLocalizedLevelName(); @@ -46,6 +51,8 @@ namespace WebfrontCore.Controllers displayLevel = Permission.User.ToLocalizedLevelName(); } + displayLevel = string.IsNullOrEmpty(client.Tag) ? displayLevel : $"{displayLevel} ({client.Tag})"; + var clientDto = new PlayerInfo() { Name = client.Name, diff --git a/WebfrontCore/ViewComponents/ServerListViewComponent.cs b/WebfrontCore/ViewComponents/ServerListViewComponent.cs index 224692ff0..012f18728 100644 --- a/WebfrontCore/ViewComponents/ServerListViewComponent.cs +++ b/WebfrontCore/ViewComponents/ServerListViewComponent.cs @@ -29,7 +29,8 @@ namespace WebfrontCore.ViewComponents Name = p.Name, ClientId = p.ClientId, Level = p.Level.ToLocalizedLevelName(), - LevelInt = (int)p.Level + LevelInt = (int)p.Level, + Tag = p.Tag }).ToList(), ChatHistory = s.ChatHistory.ToList(), Online = !s.Throttled, diff --git a/WebfrontCore/Views/Client/Privileged/Index.cshtml b/WebfrontCore/Views/Client/Privileged/Index.cshtml index f29f32ce4..f9a303518 100644 --- a/WebfrontCore/Views/Client/Privileged/Index.cshtml +++ b/WebfrontCore/Views/Client/Privileged/Index.cshtml @@ -7,7 +7,7 @@ foreach (var key in Model.Keys) {
- @key.ToString() + @Utilities.ToLocalizedLevelName(key)
diff --git a/WebfrontCore/Views/Server/_ClientActivity.cshtml b/WebfrontCore/Views/Server/_ClientActivity.cshtml index de43e762a..5cea0f975 100644 --- a/WebfrontCore/Views/Server/_ClientActivity.cshtml +++ b/WebfrontCore/Views/Server/_ClientActivity.cshtml @@ -45,57 +45,48 @@ }
-
-
- @{ - for (int i = 0; i < half; i++) +
+
+ @for (var i = 0; i < half; i++) + { + if (i > Model.Players.Count - 1) { - if (i > Model.Players.Count - 1) - { - continue; - } + continue; + } - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; -
- @if (ViewBag.Authorized) - { - - } + //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); - - - + string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; - @if (ViewBag.Authorized) - { - - } -
-
+ + + + + @if (ViewBag.Authorized) + { + } }
-
- @{ - for (int i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) +
+ @for (var i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) + { + if (i > Model.Players.Count - 1) { - if (i > Model.Players.Count - 1) - { - continue; - } + continue; + } - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; + //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); -
- - - - @if (ViewBag.Authorized) - { - - } -
-
+ string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; + + + + + + @if (ViewBag.Authorized) + { + } }