diff --git a/Application/Application.csproj b/Application/Application.csproj index d06635524..997ef1fd9 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -5,7 +5,7 @@ netcoreapp2.1 false RaidMax.IW4MAdmin.Application - 2.1.9 + 2.1.9.1 RaidMax Forever None IW4MAdmin diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json index 109de7f23..7a235b6b4 100644 --- a/Application/DefaultSettings.json +++ b/Application/DefaultSettings.json @@ -171,7 +171,7 @@ }, { - "Alias": "IW4 Credits", + "Alias": "Test map", "Name": "iw4_credits" }, @@ -190,6 +190,11 @@ "Name": "mp_cargoship_sh" }, + { + "Alias": "Cargoship", + "Name": "mp_cargoship" + }, + { "Alias": "Shipment", "Name": "mp_shipment" @@ -216,23 +221,43 @@ }, { - "Alias": "Favela - Tropical", + "Alias": "Tropical Favela", "Name": "mp_fav_tropical" }, { - "Alias": "Estate - Tropical", + "Alias": "Tropical Estate", "Name": "mp_estate_tropical" }, { - "Alias": "Crash - Tropical", + "Alias": "Tropical Crash", "Name": "mp_crash_tropical" }, { "Alias": "Forgotten City", "Name": "mp_bloc_sh" + }, + + { + "Alias": "Crossfire", + "Name": "mp_cross_fire" + }, + + { + "Alias": "Bloc", + "Name": "mp_bloc" + }, + + { + "Alias": "Oilrig", + "Name": "oilrig" + }, + + { + "Name": "Village", + "Alias": "co_hunted" } ] }, diff --git a/Application/GameEventHandler.cs b/Application/GameEventHandler.cs index dceb1b326..ef7cd695a 100644 --- a/Application/GameEventHandler.cs +++ b/Application/GameEventHandler.cs @@ -18,23 +18,23 @@ namespace IW4MAdmin.Application { Manager = mgr; OutOfOrderEvents = new SortedList(); - IsProcessingEvent = new SemaphoreSlim(2, 2); + IsProcessingEvent = new SemaphoreSlim(1, 1); } public void AddEvent(GameEvent gameEvent) { - IsProcessingEvent.Wait(); + // IsProcessingEvent.Wait(); ((Manager as ApplicationManager).OnServerEvent)(this, new GameEventArgs(null, false, gameEvent)); - if (gameEvent.Type == GameEvent.EventType.Connect) - { - IsProcessingEvent.Wait(); - if (!gameEvent.OnProcessed.Wait(30 * 1000)) - { - Manager.GetLogger().WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_TIMEOUT"]} [{gameEvent.Id}, {gameEvent.Type}]"); - } - IsProcessingEvent.Release(1); - } - IsProcessingEvent.Release(1); + // IsProcessingEvent.Release(1); + //if (gameEvent.Type == GameEvent.EventType.Connect) + //{ + // IsProcessingEvent.Wait(); + // if (!gameEvent.OnProcessed.Wait(10 * 1000)) + // { + // Manager.GetLogger().WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_TIMEOUT"]} [{gameEvent.Id}, {gameEvent.Type}]"); + // } + // IsProcessingEvent.Release(1); + //} return; #if DEBUG diff --git a/Application/Main.cs b/Application/Main.cs index 1974292ab..550731de5 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -23,20 +23,16 @@ namespace IW4MAdmin.Application public static void Main(string[] args) { AppDomain.CurrentDomain.SetData("DataDirectory", OperatingDirectory); - //System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.BelowNormal; Console.OutputEncoding = Encoding.UTF8; Console.ForegroundColor = ConsoleColor.Gray; - Version = Assembly.GetExecutingAssembly().GetName().Version.Major + - Assembly.GetExecutingAssembly().GetName().Version.Minor / 10.0f + - Assembly.GetExecutingAssembly().GetName().Version.Build / 100.0f; - Version = Math.Round(Version, 3); + Version = Utilities.GetVersionAsDouble(); Console.WriteLine("====================================================="); Console.WriteLine(" IW4M ADMIN"); Console.WriteLine(" by RaidMax "); - Console.WriteLine($" Version {Version.ToString("0.00")}"); + Console.WriteLine($" Version {Utilities.GetVersionAsString()}"); Console.WriteLine("====================================================="); Index loc = null; @@ -111,7 +107,7 @@ namespace IW4MAdmin.Application var consoleTask = Task.Run(async () => { String userInput; - Player Origin = ServerManager.GetClientService().Get(1).Result.AsPlayer(); + Player Origin = Utilities.IW4MAdminClient; do { diff --git a/Application/Manager.cs b/Application/Manager.cs index dfb188c6e..d60f81818 100644 --- a/Application/Manager.cs +++ b/Application/Manager.cs @@ -263,6 +263,7 @@ namespace IW4MAdmin.Application await new ContextSeed(db).Seed(); } + // todo: optimize this var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted)) .Select(c => new { diff --git a/Application/Server.cs b/Application/Server.cs index 905e88740..585f60603 100644 --- a/Application/Server.cs +++ b/Application/Server.cs @@ -206,7 +206,7 @@ namespace IW4MAdmin if (currentBan != null) { Logger.WriteInfo($"Banned client {player} trying to connect..."); - var autoKickClient = (await Manager.GetClientService().Get(1)).AsPlayer(); + var autoKickClient = Utilities.IW4MAdminClient; autoKickClient.CurrentServer = this; // the player is permanently banned @@ -847,7 +847,7 @@ namespace IW4MAdmin { if (Target.Warnings >= 4) { - await Target.Kick(loc["SERVER_WARNLIMT_REACHED"], (await Manager.GetClientService().Get(1)).AsPlayer()); + await Target.Kick(loc["SERVER_WARNLIMT_REACHED"], Utilities.IW4MAdminClient); return; } diff --git a/Plugins/ScriptPlugins/SharedGUIDKick.js b/Plugins/ScriptPlugins/SharedGUIDKick.js index 48ad009a0..b82f0ac5b 100644 --- a/Plugins/ScriptPlugins/SharedGUIDKick.js +++ b/Plugins/ScriptPlugins/SharedGUIDKick.js @@ -4,9 +4,15 @@ var plugin = { name: 'Shared GUID Kicker Plugin', onEventAsync: function (gameEvent, server) { - // connect event + // make sure we only check for IW4(x) + if (server.GameName !== 2) { + return false; + } + + // connect or join event if (gameEvent.Type === 3 || - gameEvent.Type === 4) { + gameEvent.Type === 4) { + // this GUID seems to have been packed in a IW4 torrent and results in an unreasonable amount of people using the same GUID if (gameEvent.Origin.NetworkId === -805366929435212061) { gameEvent.Origin.Kick('Your GUID is generic. Delete players/guids.dat and rejoin', _IW4MAdminClient); } diff --git a/SharedLibraryCore/Dtos/ClientInfo.cs b/SharedLibraryCore/Dtos/ClientInfo.cs index ec9efa4e7..63594146c 100644 --- a/SharedLibraryCore/Dtos/ClientInfo.cs +++ b/SharedLibraryCore/Dtos/ClientInfo.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using static SharedLibraryCore.Objects.Player; namespace SharedLibraryCore.Dtos { @@ -10,5 +11,7 @@ namespace SharedLibraryCore.Dtos { public string Name { get; set; } public int ClientId { get; set; } + public int LinkId { get; set; } + public Permission Level { get; set; } } } diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index a5726f384..8c0bbf5c8 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -9,6 +9,7 @@ using SharedLibraryCore.Database.Models; using System.Linq.Expressions; using SharedLibraryCore.Objects; using Microsoft.EntityFrameworkCore; +using SharedLibraryCore.Dtos; namespace SharedLibraryCore.Services { @@ -94,10 +95,9 @@ namespace SharedLibraryCore.Services { return await Task.Run(() => { - using (var context = new DatabaseContext()) + using (var context = new DatabaseContext(true)) { return context.Clients - .AsNoTracking() .Include(c => c.CurrentAlias) .Include(c => c.AliasLink.Children) .Where(e).ToList(); @@ -107,11 +107,8 @@ namespace SharedLibraryCore.Services public async Task Get(int entityID) { - using (var context = new DatabaseContext()) + using (var context = new DatabaseContext(true)) { - context.ChangeTracker.AutoDetectChangesEnabled = false; - context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - var iqClient = from client in context.Clients .Include(c => c.CurrentAlias) .Include(c => c.AliasLink.Children) @@ -128,6 +125,9 @@ namespace SharedLibraryCore.Services linkedClient.NetworkId }) }; +#if DEBUG == true + var clientSql = iqClient.ToSql(); +#endif var foundClient = await iqClient.FirstOrDefaultAsync(); if (foundClient == null) @@ -143,15 +143,19 @@ namespace SharedLibraryCore.Services } } + private static readonly Func> _getUniqueQuery = + EF.CompileAsyncQuery((DatabaseContext context, long networkId) => + context.Clients + .Include(c => c.CurrentAlias) + .Include(c => c.AliasLink.Children) + .FirstOrDefault(c => c.NetworkId == networkId) + ); + public async Task GetUnique(long entityAttribute) { - using (var context = new DatabaseContext()) + using (var context = new DatabaseContext(true)) { - return await context.Clients - .AsNoTracking() - .Include(c => c.CurrentAlias) - .Include(c => c.AliasLink.Children) - .SingleOrDefaultAsync(c => c.NetworkId == entityAttribute); + return await _getUniqueQuery(context, entityAttribute); } } @@ -219,7 +223,7 @@ namespace SharedLibraryCore.Services } } - #region ServiceSpecific +#region ServiceSpecific public async Task> GetOwners() { using (var context = new DatabaseContext()) @@ -228,32 +232,24 @@ namespace SharedLibraryCore.Services .ToListAsync(); } - public async Task IsAuthenticated(int clientIP) + public async Task> GetPrivilegedClients() { - using (var context = new DatabaseContext()) + using (var context = new DatabaseContext(disableTracking: true)) { - var iqMatching = from alias in context.Aliases - where alias.IPAddress == clientIP - join client in context.Clients - on alias.LinkId equals client.AliasLinkId - where client.Level > Player.Permission.Trusted - select client; - - return (await iqMatching.CountAsync()) > 0; - } - } - - public async Task> GetPrivilegedClients() - { - using (var context = new DatabaseContext()) - { - context.ChangeTracker.AutoDetectChangesEnabled = false; - context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - var iqClients = from client in context.Clients - .Include(c => c.CurrentAlias) where client.Level >= Player.Permission.Trusted - select client; + where client.Active + select new ClientInfo() + { + ClientId = client.ClientId, + Name = client.CurrentAlias.Name, + LinkId = client.AliasLinkId, + Level = client.Level + }; + +#if DEBUG == true + var clientsSql = iqClients.ToSql(); +#endif return await iqClients.ToListAsync(); } @@ -356,6 +352,6 @@ namespace SharedLibraryCore.Services using (var context = new DatabaseContext()) return await context.Clients.SumAsync(c => c.TotalConnectionTime); } - #endregion +#endregion } } diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 9ee978f7d..3ea5ab93a 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -507,6 +507,14 @@ namespace SharedLibraryCore return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue(); } + public static double GetVersionAsDouble() + { + string version = Assembly.GetCallingAssembly().GetName().Version.ToString(); + version = version.Replace(".", ""); + return double.Parse(version) / 1000.0; + } + + public static string GetVersionAsString() => Assembly.GetCallingAssembly().GetName().Version.ToString(); #if DEBUG == true @@ -530,7 +538,7 @@ namespace SharedLibraryCore var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false); var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor(); modelVisitor.CreateQueryExecutor(queryModel); - var sql = modelVisitor.Queries.First().ToString(); + var sql = modelVisitor.Queries.First().ToString().Replace("\"", "`"); return sql; } diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index 0824c5475..fe57d0a08 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -119,9 +119,8 @@ namespace WebfrontCore.Controllers public async Task PrivilegedAsync() { var admins = (await Manager.GetClientService().GetPrivilegedClients()) - .Where(a => a.Active) - .OrderByDescending(a => a.Level).ThenByDescending(a => a.LastConnection) - .GroupBy(a => a.AliasLinkId).Select(a => a.First()); + .OrderByDescending(a => a.Level) + .GroupBy(a => a.LinkId).Select(a => a.First()); var adminsDict = new Dictionary>();