From 2c2c442ba7a204560b272447dbe952db8535ffb8 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 26 Apr 2018 19:19:42 -0500 Subject: [PATCH] updated portuguese translation fixed issue with locale when no config present changed kick color on webfront aliased owner to iamgod (for b3 familiar users) hopefully fixed stats issue added T5M (V2 BO2) support made dvar grab at beginning minimal to prevent throttling on older CODS --- Application/EventParsers/T5MEventParser.cs | 11 +++ Application/Localization/Configure.cs | 4 +- Application/Localization/IW4MAdmin.pt-PT.json | 27 ++++--- Application/Main.cs | 2 +- Application/Manager.cs | 6 +- Application/Server.cs | 70 ++++++++++++------- Plugins/Stats/Helpers/StatManager.cs | 33 +++++---- SharedLibraryCore/Commands/NativeCommands.cs | 2 +- SharedLibraryCore/RCon/Connection.cs | 4 +- SharedLibraryCore/RCon/StaticHelpers.cs | 2 +- SharedLibraryCore/Server.cs | 5 +- SharedLibraryCore/Services/PenaltyService.cs | 22 ++++-- WebfrontCore/wwwroot/css/profile.css | 5 +- version.txt | 2 + 14 files changed, 124 insertions(+), 71 deletions(-) create mode 100644 Application/EventParsers/T5MEventParser.cs diff --git a/Application/EventParsers/T5MEventParser.cs b/Application/EventParsers/T5MEventParser.cs new file mode 100644 index 000000000..0dc32290c --- /dev/null +++ b/Application/EventParsers/T5MEventParser.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IW4MAdmin.Application.EventParsers +{ + class T5MEventParser : IW4EventParser + { + public override string GetGameDir() => "v2"; + } +} diff --git a/Application/Localization/Configure.cs b/Application/Localization/Configure.cs index eeff68aa7..ee54bb7b3 100644 --- a/Application/Localization/Configure.cs +++ b/Application/Localization/Configure.cs @@ -11,8 +11,8 @@ namespace IW4MAdmin.Application.Localization { public static void Initialize() { - string currentLocale = Program.ServerManager.GetApplicationSettings().Configuration().CustomLocale ?? - CultureInfo.CurrentCulture.Name?.Substring(0, 2); + string currentLocale = Program.ServerManager.GetApplicationSettings().Configuration()?.CustomLocale ?? + CultureInfo.CurrentCulture?.Name?.Substring(0, 2); if (currentLocale == null) throw new Exception("Computer CurrentCulture does not exist"); diff --git a/Application/Localization/IW4MAdmin.pt-PT.json b/Application/Localization/IW4MAdmin.pt-PT.json index e86a8ed9d..570c64402 100644 --- a/Application/Localization/IW4MAdmin.pt-PT.json +++ b/Application/Localization/IW4MAdmin.pt-PT.json @@ -1,9 +1,8 @@ -// translated by Daniel aka Vou te comer -{ +{ "LocalizationName": "pt-BR", "LocalizationSet": { "MANAGER_VERSION_FAIL": "Não foi possível obter a versão mais recente do IW4MAdmin", - "MANAGER_VERSION_UPDATE": "Tem uma atualização. A versão mais recente é", + "MANAGER_VERSION_UPDATE": "Há uma atualização disponível. A versão mais recente é", "MANAGER_VERSION_CURRENT": "Está é a sua versão", "MANAGER_VERSION_SUCCESS": "O IW4MAdmin está atualizado", "MANAGER_INIT_FAIL": "Erro fatal durante a inicialização", @@ -12,7 +11,7 @@ "MANAGER_MONITORING_TEXT": "Agora monitorando", "MANAGER_CONNECTION_REST": "A conexão foi reestabelecida com", "SETUP_ENABLE_WEBFRONT": "Habilitar o módulo da web do IW4MAdmin", - "SETUP_ENABLE_MULTIOWN": "Ativar vários propietários", + "SETUP_ENABLE_MULTIOWN": "Ativar vários proprietários", "SETUP_ENABLE_STEPPEDPRIV": "Ativar hierarquia de privilégios escalonada", "SETUP_ENABLE_CUSTOMSAY": "Habilitar a customização do nome do comando say", "SETUP_SAY_NAME": "Digite o nome customizado do comando say", @@ -39,10 +38,10 @@ "SERVER_ERROR_PLUGIN": "Ocorreu um erro ao carregar o plug-in", "SERVER_ERROR_ADDPLAYER": "Não foi possível adicionar o jogador", "SERVER_ERROR_POLLING": "reduzir a taxa de sondagem do server", - "SERVER_ERROR_COMMUNICATION": "Não foi possivel fazer a comunicação com", + "SERVER_ERROR_COMMUNICATION": "Não foi possível fazer a comunicação com", "SERVER_ERROR_EXCEPTION": "Exceção inesperada em", "SERVER_KICK_VPNS_NOTALLOWED": "VPNs não são permitidas neste servidor", - "SERVER_KICK_TEXT": "Você foi expluso", + "SERVER_KICK_TEXT": "Você foi expulso", "SERVER_KICK_MINNAME": "Seu nome deve conter no mínimo três caracteres", "SERVER_KICK_NAME_INUSE": "Seu nome já está sendo usado por outra pessoa", "SERVER_KICK_GENERICNAME": "Por favor, mude o seu nome usando o comando /name no console", @@ -83,9 +82,9 @@ "COMMANDS_HELP_NOTFOUND": "Não foi possível encontrar esse comando", "COMMANDS_HELP_MOREINFO": "Digite !help para saber como usar o comando", "COMMANDS_FASTRESTART_UNMASKED": "reiniciou rapidamente o mapa", - "COMMANDS_FASTRESTART_MASKED": "O mapa foi reniciado rapidamente", + "COMMANDS_FASTRESTART_MASKED": "O mapa foi reiniciado rapidamente", "COMMANDS_MAPROTATE": "Rotacionando o mapa em ^55 ^7segundos", - "COMMANDS_SETLEVEL_SELF": "Você não pode mudar seu própio nível", + "COMMANDS_SETLEVEL_SELF": "Você não pode mudar seu próprio nível", "COMMANDS_SETLEVEL_OWNER": "Só pode haver 1 dono. Modifique suas configurações se vários proprietários forem necessários", "COMMANDS_SETLEVEL_STEPPEDDISABLED": "Este servidor não permite que você promova", "COMMANDS_SETLEVEL_LEVELTOOHIGH": "Você só pode promover do ^5{0} ^7para ^5{1} ^7ou um nível menor", @@ -109,9 +108,9 @@ "COMMANDS_REPORTS_CLEAR_SUCCESS": "Lista de denúncias limpa com sucesso", "COMMANDS_REPORTS_NONE": "Ninguém foi denunciado ainda", "COMMANDS_MASK_ON": "Você foi mascarado", - "COMMANDS_MASK_OFF": "Você foi desmarcarado", + "COMMANDS_MASK_OFF": "Você foi desmascarado", "COMMANDS_BANINFO_NONE": "Nenhum banimento ativo foi encontrado para esse jogador", - "COMMANDS_BANINO_SUCCESS": "foi bannido por ^5{0} ^7por:", + "COMMANDS_BANINO_SUCCESS": "foi banido por ^5{0} ^7por:", "COMMANDS_ALIAS_ALIASES": "Nomes registrados", "COMMANDS_ALIAS_IPS": "IPs", "COMMANDS_RCON_SUCCESS": "O comando para o RCon foi enviado com sucesso", @@ -135,7 +134,7 @@ "COMMANDS_WHO_DESC": "dá informações sobre você", "COMMANDS_LIST_DESC": "lista os jogadores ativos na partida", "COMMANDS_HELP_DESC": "lista todos os comandos disponíveis", - "COMMANDS_FASTRESTART_DESC": "renincializa rapidamente o mapa, não recomendável o uso várias vezes seguidas", + "COMMANDS_FASTRESTART_DESC": "reinicializa rapidamente o mapa, não recomendável o uso várias vezes seguidas", "COMMANDS_MAPROTATE_DESC": "avança para o próximo mapa da rotação", "COMMANDS_SETLEVEL_DESC": "define o jogador para o nível de privilégio especificado", "COMMANDS_USAGE_DESC": "vê quanto o aplicativo está usando de memória ram do seu computador", @@ -164,7 +163,7 @@ "COMMANDS_ARGS_MESSAGE": "mensagem", "COMMANDS_ARGS_DURATION": "duração (minutos|horas|dias|semanas|anos)", "COMMANDS_ARGS_CLIENTID": "id do jogador", - "COMMANDS_ARGS_COMMANDS": "commandos", + "COMMANDS_ARGS_COMMANDS": "comandos", "COMMANDS_ARGS_LEVEL": "nível", "COMMANDS_ARGS_MAP": "mapa", "COMMANDS_ARGS_CLEAR": "limpar", @@ -175,7 +174,7 @@ "PLUGINS_LOGIN_COMMANDS_LOGIN_FAIL": "Sua senha está errada", "PLUGINS_STATS_COMMANDS_RESET_DESC": "reinicia suas estatísticas para uma nova", "PLUGINS_STATS_COMMANDS_RESET_SUCCESS": "Suas estatísticas nesse servidor foram reiniciadas", - "PLUGINS_STATS_COMMANDS_RESET_FAIL": "Você deve estar connectado a um servidor para reiniciar as suas estatísticas", + "PLUGINS_STATS_COMMANDS_RESET_FAIL": "Você deve estar conectado a um servidor para reiniciar as suas estatísticas", "PLUGINS_STATS_COMMANDS_VIEW_DESC": "mostra suas estatísticas", "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME": "o jogador especificado deve estar jogando", "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME_SELF": "Você deve estar no jogo para ver suas estatísticas", @@ -195,4 +194,4 @@ "GLOBAL_INFO": "Informação", "GLOBAL_VERBOSE": "Verbose" } -} \ No newline at end of file +} diff --git a/Application/Main.cs b/Application/Main.cs index cf96bbbc3..9ee3ff3c7 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -41,7 +41,7 @@ namespace IW4MAdmin.Application ServerManager = ApplicationManager.GetInstance(); - using (var db = new DatabaseContext(ServerManager.GetApplicationSettings().Configuration().ConnectionString)) + using (var db = new DatabaseContext(ServerManager.GetApplicationSettings().Configuration()?.ConnectionString)) new ContextSeed(db).Seed().Wait(); var api = API.Master.Endpoint.Get(); diff --git a/Application/Manager.cs b/Application/Manager.cs index 4fe102d2e..b9ade6e12 100644 --- a/Application/Manager.cs +++ b/Application/Manager.cs @@ -92,10 +92,14 @@ namespace IW4MAdmin.Application public void UpdateStatus(object state) { + var taskList = new List(); + foreach (var server in Servers) { - Task.Run(() => server.ProcessUpdatesAsync(new CancellationToken())); + taskList.Add(Task.Run(() => server.ProcessUpdatesAsync(new CancellationToken()))); } + + Task.WaitAll(taskList.ToArray()); } public async Task Init() diff --git a/Application/Server.cs b/Application/Server.cs index f520ffa99..b382696c1 100644 --- a/Application/Server.cs +++ b/Application/Server.cs @@ -183,9 +183,10 @@ namespace IW4MAdmin Logger.WriteInfo($"Client {player} connecting..."); + var e = new GameEvent(GameEvent.EventType.Connect, "", player, null, this); + Manager.GetEventHandler().AddEvent(e); - Manager.GetEventHandler().AddEvent(new GameEvent(GameEvent.EventType.Connect, "", player, null, this)); - + e.OnProcessed.Wait(); if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs && await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().Configuration().IPHubAPIKey)) @@ -212,7 +213,9 @@ namespace IW4MAdmin Player Leaving = Players[cNum]; Logger.WriteInfo($"Client {Leaving} disconnecting..."); - Manager.GetEventHandler().AddEvent(new GameEvent(GameEvent.EventType.Disconnect, "", Leaving, null, this)); + var e = new GameEvent(GameEvent.EventType.Disconnect, "", Leaving, null, this); + Manager.GetEventHandler().AddEvent(e); + e.OnProcessed.Wait(); Leaving.TotalConnectionTime += (int)(DateTime.UtcNow - Leaving.ConnectionTime).TotalSeconds; Leaving.LastConnection = DateTime.UtcNow; @@ -394,7 +397,7 @@ namespace IW4MAdmin // hack: this prevents commands from getting executing that 'shouldn't' be if (E.Type == GameEvent.EventType.Command && E.Extra != null && - (canExecuteCommand || + (canExecuteCommand || E.Origin?.Level == Player.Permission.Console)) { await (((Command)E.Extra).ExecuteAsync(E)); @@ -697,6 +700,7 @@ namespace IW4MAdmin if (ServerConfig.UseIW5MParser) RconParser = new IW5MRConParser(); + var version = await this.GetDvarAsync("version"); GameName = Utilities.GetGame(version.Value); @@ -704,26 +708,41 @@ namespace IW4MAdmin EventParser = new IW4EventParser(); else if (GameName == Game.IW5) EventParser = new IW5EventParser(); + else if (GameName == Game.T5M) + EventParser = new T5MEventParser(); else if (GameName == Game.T6M) EventParser = new T6MEventParser(); - else if (GameName == Game.UKN) - Logger.WriteWarning($"Game name not recognized: {version}"); else EventParser = new IW3EventParser(); // this uses the 'main' folder for log paths - var shortversion = await this.GetDvarAsync("shortversion"); - var hostname = await this.GetDvarAsync("sv_hostname"); - var mapname = await this.GetDvarAsync("mapname"); - var maxplayers = (GameName == Game.IW4) ? // gotta love IW4 idiosyncrasies - await this.GetDvarAsync("party_maxplayers") : - await this.GetDvarAsync("sv_maxclients"); - var gametype = await this.GetDvarAsync("g_gametype"); + if (GameName == Game.UKN) + Logger.WriteWarning($"Game name not recognized: {version}"); + + var infoResponse = await this.GetInfoAsync(); + // this is normally slow, but I'm only doing it because different games have different prefixes + var hostname = infoResponse == null ? + (await this.GetDvarAsync("sv_hostname")).Value : + infoResponse.Where(kvp => kvp.Key.Contains("hostname")).Select(kvp => kvp.Value).First(); + var mapname = infoResponse == null ? + (await this.GetDvarAsync("mapname")).Value : + infoResponse["mapname"]; + int maxplayers = (GameName == Game.IW4) ? // gotta love IW4 idiosyncrasies + (await this.GetDvarAsync("party_maxplayers")).Value : + infoResponse == null ? + (await this.GetDvarAsync("sv_maxclients")).Value : + Convert.ToInt32(infoResponse["sv_maxclients"]); + var gametype = infoResponse == null ? + (await this.GetDvarAsync("g_gametype")).Value : + infoResponse.Where(kvp => kvp.Key.Contains("gametype")).Select(kvp => kvp.Value).First(); var basepath = await this.GetDvarAsync("fs_basepath"); - WorkingDirectory = basepath.Value; - var game = await this.GetDvarAsync("fs_game"); + var game = infoResponse == null || !infoResponse.ContainsKey("fs_game") ? + (await this.GetDvarAsync("fs_game")).Value : + infoResponse["fs_game"]; var logfile = await this.GetDvarAsync("g_log"); var logsync = await this.GetDvarAsync("g_logsync"); + WorkingDirectory = basepath.Value; + try { var website = await this.GetDvarAsync("_website"); @@ -737,11 +756,11 @@ namespace IW4MAdmin InitializeMaps(); - this.Hostname = hostname.Value.StripColors(); - this.CurrentMap = Maps.Find(m => m.Name == mapname.Value) ?? new Map() { Alias = mapname.Value, Name = mapname.Value }; - this.MaxClients = maxplayers.Value; - this.FSGame = game.Value; - this.Gametype = gametype.Value; + this.Hostname = hostname.StripColors(); + this.CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname }; + this.MaxClients = maxplayers; + this.FSGame = game; + this.Gametype = gametype; //wait this.SetDvarAsync("sv_kickbantime", 60); @@ -759,7 +778,7 @@ namespace IW4MAdmin CustomCallback = await ScriptLoaded(); string mainPath = EventParser.GetGameDir(); #if DEBUG - basepath.Value = @"\\192.168.88.253\mw2\"; + basepath.Value = @"\\192.168.88.253\Call of Duty 4\"; #endif string logPath; if (GameName == Game.IW5) @@ -768,9 +787,9 @@ namespace IW4MAdmin } else { - logPath = game.Value == string.Empty ? + logPath = game == string.Empty ? $"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile.Value}" : - $"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Value.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}"; + $"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}"; } @@ -789,10 +808,9 @@ namespace IW4MAdmin } else { - // LogFile = new IFile(logPath); - + LogEvent = new GameLogEvent(this, logPath, logfile.Value); } - LogEvent = new GameLogEvent(this, logPath, logfile.Value); + Logger.WriteInfo($"Log file is {logPath}"); #if DEBUG // LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php"); diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 221d1dd12..8f7c02855 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -84,7 +84,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// EFClientStatistic of specified player public async Task AddPlayer(Player pl) { - Log.WriteInfo($"Adding {pl} to stats"); int serverId = pl.CurrentServer.GetHashCode(); if (!Servers.ContainsKey(serverId)) @@ -95,6 +94,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers var playerStats = Servers[serverId].PlayerStats; var statsSvc = ContextThreads[serverId]; + var detectionStats = Servers[serverId].PlayerDetections; + + if (playerStats.ContainsKey(pl.ClientId)) + { + Log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId}"); + return null; + } // get the client's stats from the database if it exists, otherwise create and attach a new one // if this fails we want to throw an exception @@ -142,19 +148,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers clientStats.LastStatCalculation = DateTime.UtcNow; clientStats.SessionScore = pl.Score; - if (playerStats.ContainsKey(pl.ClientId)) - { - Log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId} vs {playerStats[pl.ClientId].ClientId}"); - playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue); - } - playerStats.TryAdd(pl.ClientId, clientStats); + Log.WriteInfo($"Adding {pl} to stats"); - var detectionStats = Servers[serverId].PlayerDetections; + if (!playerStats.TryAdd(pl.ClientId, clientStats)) + Log.WriteDebug($"Could not add client to stats {pl}"); - if (detectionStats.ContainsKey(pl.ClientId)) - detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue); + if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats))) + Log.WriteDebug("Could not add client to detection"); - detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)); // todo: look at this more statsSvc.ClientStatSvc.Update(clientStats); @@ -181,6 +182,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers if (!playerStats.ContainsKey(pl.ClientId)) { Log.WriteWarning($"Client disconnecting not in stats {pl}"); + // remove the client from the stats dictionary as they're leaving + playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue1); + detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue2); return; } @@ -188,9 +192,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers var clientStats = playerStats[pl.ClientId]; // sync their score clientStats.SessionScore += (pl.Score - clientStats.LastScore); + // remove the client from the stats dictionary as they're leaving - playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue); - detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue2); + playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue3); + detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue4); // sync their stats before they leave clientStats = UpdateStats(clientStats); @@ -421,7 +426,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { // prevent NaN or inactive time lowering SPM if ((DateTime.UtcNow - clientStats.LastStatCalculation).TotalSeconds / 60.0 < 0.01 || - (DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0 > 3 || + (DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0 > 3 || clientStats.SessionScore < 1) return clientStats; diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 302e98591..0860ba144 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -27,7 +27,7 @@ namespace SharedLibraryCore.Commands public class COwner : Command { public COwner() : - base("owner", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_OWNER_DESC"], "o", Player.Permission.User, false) + base("owner", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_OWNER_DESC"], "iamgod", Player.Permission.User, false) { } public override async Task ExecuteAsync(GameEvent E) diff --git a/SharedLibraryCore/RCon/Connection.cs b/SharedLibraryCore/RCon/Connection.cs index 9d30ed123..3bc232fc9 100644 --- a/SharedLibraryCore/RCon/Connection.cs +++ b/SharedLibraryCore/RCon/Connection.cs @@ -163,9 +163,9 @@ namespace SharedLibraryCore.RCon public async Task SendQueryAsync(StaticHelpers.QueryType type, string parameters = "", bool waitForResponse = true) { // will this really prevent flooding? - if ((DateTime.Now - LastQuery).TotalMilliseconds < 35) + if ((DateTime.Now - LastQuery).TotalMilliseconds < 150) { - await Task.Delay(35); + await Task.Delay(150); } LastQuery = DateTime.Now; diff --git a/SharedLibraryCore/RCon/StaticHelpers.cs b/SharedLibraryCore/RCon/StaticHelpers.cs index 0782d0391..04d10d06d 100644 --- a/SharedLibraryCore/RCon/StaticHelpers.cs +++ b/SharedLibraryCore/RCon/StaticHelpers.cs @@ -13,6 +13,6 @@ namespace SharedLibraryCore.RCon } public static char SeperatorChar = (char)int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier); - public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 10); + public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 2); } } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 053b7b031..4e2e3c265 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -109,10 +109,7 @@ namespace SharedLibraryCore /// abstract public Task ValidateCommand(GameEvent E); - virtual public Task ProcessUpdatesAsync(CancellationToken cts) - { - return null; - } + virtual public Task ProcessUpdatesAsync(CancellationToken cts) => (Task)Task.CompletedTask; /// /// Process any server event diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index c3e82a4c6..d0bb799a6 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -7,6 +7,7 @@ using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using Microsoft.EntityFrameworkCore; +using SharedLibraryCore.Objects; namespace SharedLibraryCore.Services { @@ -135,16 +136,17 @@ namespace SharedLibraryCore.Services { if (victim) { + context.ChangeTracker.AutoDetectChangesEnabled = false; var now = DateTime.UtcNow; var iqPenalties = from penalty in context.Penalties.AsNoTracking() where penalty.OffenderId == clientId join victimClient in context.Clients.AsNoTracking() on penalty.OffenderId equals victimClient.ClientId - join victimAlias in context.Aliases + join victimAlias in context.Aliases.AsNoTracking() on victimClient.CurrentAliasId equals victimAlias.AliasId - join punisherClient in context.Clients + join punisherClient in context.Clients.AsNoTracking() on penalty.PunisherId equals punisherClient.ClientId - join punisherAlias in context.Aliases + join punisherAlias in context.Aliases.AsNoTracking() on punisherClient.CurrentAliasId equals punisherAlias.AliasId //orderby penalty.When descending select new ProfileMeta() @@ -170,6 +172,9 @@ namespace SharedLibraryCore.Services var pi = ((PenaltyInfo)p.Value); if (pi.TimeRemaining.Length > 0) pi.TimeRemaining = (DateTime.Parse(((PenaltyInfo)p.Value).TimeRemaining) - now).TimeSpanText(); + // todo: why does this have to be done? + if (pi.Type.Length > 2) + pi.Type = ((Penalty.PenaltyType)Convert.ToInt32(pi.Type)).ToString(); } ); return list; @@ -203,7 +208,16 @@ namespace SharedLibraryCore.Services When = penalty.When }; // fixme: is this good and fast? - return await iqPenalties.ToListAsync(); + var list = await iqPenalties.ToListAsync(); + + list.ForEach(p => + { + // todo: why does this have to be done? + if (((PenaltyInfo)p.Value).Type.Length < 2) + ((PenaltyInfo)p.Value).Type = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).Type)).ToString(); + }); + + return list; } diff --git a/WebfrontCore/wwwroot/css/profile.css b/WebfrontCore/wwwroot/css/profile.css index 057cd4eca..d3ea1572d 100644 --- a/WebfrontCore/wwwroot/css/profile.css +++ b/WebfrontCore/wwwroot/css/profile.css @@ -84,7 +84,10 @@ color: white; } -.penalties-color-kick, +.penalties-color-kick { + color: rgb(182, 129, 43); +} + .penalties-color-unban { color: #749363; color: rgba(116, 147, 99, 1); diff --git a/version.txt b/version.txt index 8be26213d..5815a9641 100644 --- a/version.txt +++ b/version.txt @@ -2,6 +2,8 @@ Version 2.1: CHANGELOG: -add support for localization -upgraded projects to .NET Core 2.0.7 +-redid the event system to haev a single line of execution +-added support for MySQL provider via "ConnectrionString" Version 2.0: CHANGELOG: