diff --git a/Application/Application.csproj b/Application/Application.csproj index f44efd9fb..15461232e 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -6,7 +6,7 @@ 2.2.2 false RaidMax.IW4MAdmin.Application - 2.2.5.9 + 2.2.6.0 RaidMax Forever None IW4MAdmin @@ -31,8 +31,8 @@ true true - 2.2.5.9 - 2.2.5.8 + 2.2.6.0 + 2.2.6.0 diff --git a/Application/EventParsers/BaseEventParser.cs b/Application/EventParsers/BaseEventParser.cs index a5dc40918..979456304 100644 --- a/Application/EventParsers/BaseEventParser.cs +++ b/Application/EventParsers/BaseEventParser.cs @@ -73,6 +73,8 @@ namespace IW4MAdmin.Application.EventParsers public Game GameName { get; set; } = Game.COD; + public string URLProtocolFormat { get; set; } = "CoD://{{ip}}:{{port}}"; + public virtual GameEvent GetEvent(Server server, string logLine) { logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim(); diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 17f5c0ad9..bb79469be 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -45,19 +45,16 @@ namespace IW4MAdmin if (client == null) { Logger.WriteDebug($"Client {clientFromLog} first time connecting"); + clientFromLog.CurrentServer = this; client = await Manager.GetClientService().Create(clientFromLog); } - // client has connected in the past - else + /// this is only a temporary version until the IPAddress is transmitted + client.CurrentAlias = new EFAlias() { - // this is only a temporary version until the IPAddress is transmitted - client.CurrentAlias = new EFAlias - { - Name = clientFromLog.Name, - IPAddress = clientFromLog.IPAddress - }; - } + Name = clientFromLog.Name, + IPAddress = clientFromLog.IPAddress + }; Logger.WriteInfo($"Client {client} connected..."); @@ -209,16 +206,18 @@ namespace IW4MAdmin // they're already connected if (existingClient != null) { + Logger.WriteWarning($"detected preconnect for {E.Origin}, but they are already connected"); return false; } CONNECT: - // we can go ahead and put them in if (Clients[E.Origin.ClientNumber] == null) { #if DEBUG == true Logger.WriteDebug($"Begin PreConnect for {E.Origin}"); #endif + // we can go ahead and put them in so that they don't get re added + Clients[E.Origin.ClientNumber] = E.Origin; await OnClientConnected(E.Origin); ChatHistory.Add(new ChatInfo() @@ -314,28 +313,6 @@ namespace IW4MAdmin await Warn(E.Data, E.Target, E.Origin); } - //else if (E.Type == GameEvent.EventType.Quit) - //{ - // var origin = GetClientsAsList().FirstOrDefault(_client => _client.NetworkId.Equals(E.Origin)); - - // if (origin != null) - // { - // var e = new GameEvent() - // { - // Type = GameEvent.EventType.Disconnect, - // Origin = origin, - // Owner = this - // }; - - // Manager.GetEventHandler().AddEvent(e); - // } - - // else - // { - // return false; - // } - //} - else if (E.Type == GameEvent.EventType.Disconnect) { ChatHistory.Add(new ChatInfo() @@ -351,13 +328,6 @@ namespace IW4MAdmin else if (E.Type == GameEvent.EventType.PreDisconnect) { - //if ((DateTime.UtcNow - SessionStart).TotalSeconds < 30) - //{ - // Logger.WriteInfo($"Cancelling pre disconnect for {E.Origin} as it occured too close to map end"); - // E.FailReason = GameEvent.EventFailReason.Invalid; - // return false; - //} - // predisconnect comes from minimal rcon polled players and minimal log players // so we need to disconnect the "full" version of the client var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin)); @@ -375,7 +345,7 @@ namespace IW4MAdmin else { - Logger.WriteDebug($"Client {E.Origin} detected as disconnecting, but could not find them in the player list"); + Logger.WriteWarning($"Client {E.Origin} detected as disconnecting, but could not find them in the player list"); Logger.WriteDebug($"Expected {E.Origin} but found {GetClientsAsList().FirstOrDefault(_client => _client.ClientNumber == E.Origin.ClientNumber)}"); return false; } @@ -488,9 +458,9 @@ namespace IW4MAdmin return true; } - private Task OnClientUpdate(EFClient origin) + private async Task OnClientUpdate(EFClient origin) { - var client = Clients[origin.ClientNumber]; + var client = Clients.FirstOrDefault(_client => _client.Equals(origin)); if (client != null) { @@ -500,11 +470,9 @@ namespace IW4MAdmin // update their IP if it hasn't been set yet if (client.IPAddress == null && !client.IsBot) { - return client.OnJoin(origin.IPAddress); + await client.OnJoin(origin.IPAddress); } } - - return Task.CompletedTask; } /// @@ -582,7 +550,7 @@ namespace IW4MAdmin foreach (var disconnectingClient in polledClients[1]) { - if (disconnectingClient.State == EFClient.ClientState.Disconnecting) + if (disconnectingClient.State == ClientState.Disconnecting) { continue; } diff --git a/Plugins/ScriptPlugins/ParserCoD4x.js b/Plugins/ScriptPlugins/ParserCoD4x.js index 4850f6460..ff6c5caa4 100644 --- a/Plugins/ScriptPlugins/ParserCoD4x.js +++ b/Plugins/ScriptPlugins/ParserCoD4x.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'FrenchFry, RaidMax', - version: 0.2, + version: 0.3, name: 'CoD4x Parser', isParser: true, @@ -27,6 +27,7 @@ var plugin = { eventParser.Configuration.GameDirectory = 'main'; eventParser.Version = 'CoD4 X 1.8 win_mingw-x86 build 2055 May 2 2017'; eventParser.GameName = 1; // IW3 + eventParser.URLProtocolFormat = 'cod4://{{ip}}:{{port}}'; }, onUnloadAsync: function () { diff --git a/Plugins/ScriptPlugins/ParserIW4x.js b/Plugins/ScriptPlugins/ParserIW4x.js index 838537181..cfcd8e9c2 100644 --- a/Plugins/ScriptPlugins/ParserIW4x.js +++ b/Plugins/ScriptPlugins/ParserIW4x.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.2, + version: 0.3, name: 'IW4 Parser', isParser: true, @@ -25,6 +25,7 @@ var plugin = { rconParser.GameName = 2; // IW4x eventParser.Version = 'IW4x (v0.6.0)'; eventParser.GameName = 2; // IW4x + eventParser.URLProtocolFormat = 'iw4x://{{ip}}:{{port}}'; }, onUnloadAsync: function () { diff --git a/SharedLibraryCore/Database/Models/EFAlias.cs b/SharedLibraryCore/Database/Models/EFAlias.cs index d276d9f5c..f0cce2eb6 100644 --- a/SharedLibraryCore/Database/Models/EFAlias.cs +++ b/SharedLibraryCore/Database/Models/EFAlias.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace SharedLibraryCore.Database.Models { - public class EFAlias : SharedEntity + public partial class EFAlias : SharedEntity { [Key] public int AliasId { get; set; } diff --git a/SharedLibraryCore/Helpers/PlayerHistory.cs b/SharedLibraryCore/Helpers/PlayerHistory.cs index d7c543dcd..2b1104518 100644 --- a/SharedLibraryCore/Helpers/PlayerHistory.cs +++ b/SharedLibraryCore/Helpers/PlayerHistory.cs @@ -11,19 +11,10 @@ namespace SharedLibraryCore.Helpers { DateTime t = DateTime.UtcNow; When = new DateTime(t.Year, t.Month, t.Day, t.Hour, Math.Min(59, UpdateInterval * (int)Math.Round(t.Minute / (float)UpdateInterval)), 0); - PlayerCount = cNum; + y = cNum; } -#if DEBUG - public PlayerHistory(DateTime t, int cNum) - { - When = new DateTime(t.Year, t.Month, t.Day, t.Hour, Math.Min(59, UpdateInterval * (int)Math.Round(t.Minute / (float)UpdateInterval)), 0); - PlayerCount = cNum; - } -#endif - private DateTime When; - private int PlayerCount; /// /// Used by CanvasJS as a point on the x axis @@ -36,16 +27,9 @@ namespace SharedLibraryCore.Helpers } } - /// /// Used by CanvasJS as a point on the y axis /// - public int y - { - get - { - return PlayerCount; - } - } + public int y { get; } } } diff --git a/SharedLibraryCore/Interfaces/IEventParser.cs b/SharedLibraryCore/Interfaces/IEventParser.cs index 6b097e8d1..4f05ccd57 100644 --- a/SharedLibraryCore/Interfaces/IEventParser.cs +++ b/SharedLibraryCore/Interfaces/IEventParser.cs @@ -27,5 +27,10 @@ namespace SharedLibraryCore.Interfaces /// specifies the game name (usually the internal studio iteration ie: IW4, T5 etc...) /// Game GameName { get; set; } + + /// + /// specifies the connect URI used to join game servers via web browser + /// + string URLProtocolFormat { get; set; } } } diff --git a/SharedLibraryCore/Objects/Alias.cs b/SharedLibraryCore/Objects/Alias.cs deleted file mode 100644 index 9a25ed76c..000000000 --- a/SharedLibraryCore/Objects/Alias.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SharedLibraryCore.Objects -{ - public class Alias : Database.Models.EFAlias - { - - } -} diff --git a/SharedLibraryCore/Objects/EFAlias.cs b/SharedLibraryCore/Objects/EFAlias.cs new file mode 100644 index 000000000..30105e940 --- /dev/null +++ b/SharedLibraryCore/Objects/EFAlias.cs @@ -0,0 +1,7 @@ +namespace SharedLibraryCore.Database.Models +{ + public partial class EFAlias + { + + } +} diff --git a/SharedLibraryCore/Objects/EFClient.cs b/SharedLibraryCore/Objects/EFClient.cs index b8104b401..e737f5c20 100644 --- a/SharedLibraryCore/Objects/EFClient.cs +++ b/SharedLibraryCore/Objects/EFClient.cs @@ -80,13 +80,12 @@ namespace SharedLibraryCore.Database.Models { { "_reportCount", 0 } }; - CurrentAlias = new EFAlias(); ReceivedPenalties = new List(); } public override string ToString() { - return $"{Name}::{NetworkId}"; + return $"{CurrentAlias?.Name ?? "--"}::{NetworkId}"; } /// diff --git a/SharedLibraryCore/Services/AliasService.cs b/SharedLibraryCore/Services/AliasService.cs index fe4b4d2dc..511882c4d 100644 --- a/SharedLibraryCore/Services/AliasService.cs +++ b/SharedLibraryCore/Services/AliasService.cs @@ -17,27 +17,6 @@ namespace SharedLibraryCore.Services public async Task Create(EFAlias entity) { throw await Task.FromResult(new Exception()); - /*using (var context = new DatabaseContext()) - { - var alias = new EFAlias() - { - Active = true, - DateAdded = DateTime.UtcNow, - IPAddress = entity.IPAddress, - Name = entity.Name - }; - - entity.Link = await context.AliasLinks - .FirstAsync(a => a.AliasLinkId == entity.Link.AliasLinkId); - context.Aliases.Add(entity); - await context.SaveChangesAsync(); - return entity; - }*/ - } - - public Task CreateProxy() - { - return null; } public async Task Delete(EFAlias entity) diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index e241e51bb..d8a3381f9 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -28,9 +28,12 @@ namespace SharedLibraryCore.Services if (existingAlias != null) { + entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing link {existingAlias.LinkId}"); + linkId = existingAlias.LinkId; if (existingAlias.Name == entity.Name) { + entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing alias {existingAlias.AliasId}"); aliasId = existingAlias.AliasId; } } @@ -44,9 +47,12 @@ namespace SharedLibraryCore.Services NetworkId = entity.NetworkId }; + context.Clients.Add(client); + // they're just using a new GUID if (aliasId.HasValue) { + entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s alias id and linkid to ({aliasId.Value}, {linkId.Value})"); client.CurrentAliasId = aliasId.Value; client.AliasLinkId = linkId.Value; } @@ -54,8 +60,9 @@ namespace SharedLibraryCore.Services // link was found but they don't have an exact alias else if (!aliasId.HasValue && linkId.HasValue) { + entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s linkid to {linkId.Value}, but creating new alias"); client.AliasLinkId = linkId.Value; - client.CurrentAlias = new Alias() + client.CurrentAlias = new EFAlias() { Name = entity.Name, DateAdded = DateTime.UtcNow, @@ -67,18 +74,22 @@ namespace SharedLibraryCore.Services // brand new players (supposedly) else { - client.AliasLink = new EFAliasLink(); - - client.CurrentAlias = new Alias() + entity.CurrentServer.Logger.WriteDebug($"[create] creating new Link and Alias for {entity}"); + var link = new EFAliasLink(); + var alias = new EFAlias() { Name = entity.Name, DateAdded = DateTime.UtcNow, IPAddress = entity.IPAddress, - Link = client.AliasLink, + Link = link }; + + link.Children.Add(alias); + + client.AliasLink = link; + client.CurrentAlias = alias; } - context.Clients.Add(client); await context.SaveChangesAsync(); return client; @@ -474,11 +485,6 @@ namespace SharedLibraryCore.Services .CountAsync(); } } - - public Task CreateProxy() - { - throw new NotImplementedException(); - } #endregion } } diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index e4826ebe4..c458b7d20 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -68,11 +68,6 @@ namespace SharedLibraryCore.Services return newEntity; } - public Task CreateProxy() - { - throw new NotImplementedException(); - } - public Task Delete(EFPenalty entity) { throw new NotImplementedException(); diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 29141ee08..fecbb60cc 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.IO; using System.Linq; using System.Reflection; using System.Text; @@ -716,6 +715,20 @@ namespace SharedLibraryCore return Assembly.GetCallingAssembly().GetName().Version.ToString(); } + public static string FormatExt(this string input, params object[] values) + { + var matches = Regex.Matches(Regex.Unescape(input), @"{{\w+}}"); + string output = input; + int index = 0; + foreach (Match match in matches) + { + output = output.Replace(match.Value.ToString(), $"{{{index.ToString()}}}"); + index++; + } + + return string.Format(output, values); + } + #if DEBUG == true private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); diff --git a/WebfrontCore/Controllers/ServerController.cs b/WebfrontCore/Controllers/ServerController.cs index 8624702de..de4c1d2d0 100644 --- a/WebfrontCore/Controllers/ServerController.cs +++ b/WebfrontCore/Controllers/ServerController.cs @@ -11,7 +11,7 @@ namespace WebfrontCore.Controllers [ResponseCache(NoStore = true, Duration = 0)] public IActionResult ClientActivity(long id) { - var s = Manager.GetServers().FirstOrDefault(s2 => s2.EndPoint == id); + var s = Manager.GetServers().FirstOrDefault(_server => _server.EndPoint == id); if (s == null) { diff --git a/WebfrontCore/Views/Server/_ClientActivity.cshtml b/WebfrontCore/Views/Server/_ClientActivity.cshtml index 0a6bc89ff..0101933db 100644 --- a/WebfrontCore/Views/Server/_ClientActivity.cshtml +++ b/WebfrontCore/Views/Server/_ClientActivity.cshtml @@ -36,6 +36,10 @@ @{ for (int i = 0; i < half; i++) { + if (i > Model.Players.Count - 1) + { + continue; + } string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; @Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })
} @@ -45,6 +49,10 @@ @{ for (int i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) { + if (i > Model.Players.Count - 1) + { + continue; + } string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; @Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })
} diff --git a/WebfrontCore/Views/Server/_Server.cshtml b/WebfrontCore/Views/Server/_Server.cshtml index baf2e216f..2345fbbb6 100644 --- a/WebfrontCore/Views/Server/_Server.cshtml +++ b/WebfrontCore/Views/Server/_Server.cshtml @@ -1,6 +1,4 @@ - -@model SharedLibraryCore.Dtos.ServerInfo - +@model SharedLibraryCore.Dtos.ServerInfo @{ Layout = null; } @@ -12,7 +10,12 @@
- @await Html.PartialAsync("../Server/_ClientActivity", Model) +
+
+
+
+ @await Html.PartialAsync("../Server/_ClientActivity", Model) +