diff --git a/Admin/Logger.cs b/Admin/Logger.cs index 152329a95..15ab16583 100644 --- a/Admin/Logger.cs +++ b/Admin/Logger.cs @@ -19,11 +19,12 @@ namespace IW4MAdmin } string FileName; + object ThreadLock; public Logger(string fn) { FileName = fn; - + ThreadLock = new object(); if (File.Exists(fn)) File.Delete(fn); } @@ -31,16 +32,19 @@ namespace IW4MAdmin void Write(string msg, LogType type) { string LogLine = $"[{DateTime.Now.ToString("HH:mm:ss")}] - {type}: {msg}"; + lock (ThreadLock) + { #if DEBUG // lets keep it simple and dispose of everything quickly as logging wont be that much (relatively) Console.WriteLine(LogLine); File.AppendAllText(FileName, LogLine + Environment.NewLine); #else - if (type == LogType.Error || type == LogType.Verbose) + //if (type == LogType.Error || type == LogType.Verbose) Console.WriteLine(LogLine); - if (type != LogType.Debug) + //if (type != LogType.Debug) File.AppendAllText(FileName, LogLine + Environment.NewLine); + } #endif } diff --git a/Admin/Main.cs b/Admin/Main.cs index 14dca0011..4426fe77b 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -36,7 +36,7 @@ namespace IW4MAdmin ServerManager = Manager.GetInstance(); ServerManager.Init(); - /*Task.Run(() => + Task.Run(() => { String userInput; Player Origin = new Player("IW4MAdmin", "", -1, Player.Permission.Console, -1, "", 0, ""); @@ -56,7 +56,7 @@ namespace IW4MAdmin Console.Write('>'); } while (userInput != null && ServerManager.Running); - });*/ + }); } diff --git a/Admin/Server.cs b/Admin/Server.cs index ed554c55e..3871ed618 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -46,6 +46,8 @@ namespace IW4MAdmin return allAliases; GetAliases(allAliases, currentIdentityAliases); + if (Origin.Alias != null) + allAliases.Add(Origin.Alias); return allAliases; } @@ -188,6 +190,8 @@ namespace IW4MAdmin Players[cNum] = null; ClientNum--; + if (ClientNum == 0) + chatHistory.Clear(); } } @@ -304,7 +308,7 @@ namespace IW4MAdmin else E.Target = clientFromName(Args[0]); - if (E.Target == null) + if (E.Target == null && C.needsTarget) { await E.Origin.Tell("Unable to find specified player."); throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} specified invalid player for \"{C.Name}\""); @@ -570,7 +574,7 @@ namespace IW4MAdmin if (E.Data.Length < 2) // ITS A LIE! return; - if (E.Data.Substring(0, 1) == "!" || E.Origin.Level == Player.Permission.Console) + if (E.Data.Substring(0, 1) == "!" || E.Data.Substring(0, 1) == "@" || E.Origin.Level == Player.Permission.Console) { Command C = null; @@ -603,6 +607,10 @@ namespace IW4MAdmin Logger.WriteError(String.Format("A command request \"{0}\" generated an error.", C.Name)); Logger.WriteDebug(String.Format("Error Message: {0}", Except.Message)); Logger.WriteDebug(String.Format("Error Trace: {0}", Except.StackTrace)); + await E.Origin.Tell("^1An internal error occured while processing your command^7"); +#if DEBUG + await E.Origin.Tell(Except.Message); +#endif return; } } diff --git a/Admin/WebService.cs b/Admin/WebService.cs index b1cc1048a..a705da826 100644 --- a/Admin/WebService.cs +++ b/Admin/WebService.cs @@ -592,6 +592,7 @@ namespace IW4MAdmin resp.additionalHeaders = new Dictionary(); bool authed = Manager.GetInstance().GetClientDatabase().GetAdmins().FindAll(x => x.IP == querySet["IP"]).Count > 0; + bool recent = false; if (querySet["id"] != null) { @@ -611,6 +612,7 @@ namespace IW4MAdmin else if (querySet["recent"] != null) { matchedPlayers = Manager.GetInstance().GetClientDatabase().GetRecentPlayers(); + recent = true; } if (matchedPlayers != null && matchedPlayers.Count > 0) @@ -618,8 +620,6 @@ namespace IW4MAdmin foreach (var pp in matchedPlayers) { if (pp == null) continue; - - var playerAliases = Manager.GetInstance().Servers.First().GetAliases(pp); PlayerInfo eachPlayer = new PlayerInfo(); eachPlayer.playerID = pp.DatabaseID; eachPlayer.playerIP = pp.IP; @@ -630,10 +630,13 @@ namespace IW4MAdmin eachPlayer.authed = authed; eachPlayer.showV2Features = false; - foreach (var a in playerAliases) + if (!recent) { - eachPlayer.playerAliases = a.Names; - eachPlayer.playerIPs = a.IPS; + foreach (var a in Manager.GetInstance().Servers.First().GetAliases(pp)) + { + eachPlayer.playerAliases = a.Names; + eachPlayer.playerIPs = a.IPS; + } } eachPlayer.playerConnections = pp.Connections; diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index d3567c031..1054f502d 100644 Binary files a/Admin/lib/SharedLibrary.dll and b/Admin/lib/SharedLibrary.dll differ diff --git a/Admin/webfront/header.html b/Admin/webfront/header.html index 2a142bc13..11599a9aa 100644 --- a/Admin/webfront/header.html +++ b/Admin/webfront/header.html @@ -115,6 +115,7 @@ function getColorForLevel(level, name) case "User": return "" + name + ""; case "Flagged": + case "Flag": case "TempBan": return "" + name + ""; case "Banned": @@ -123,6 +124,7 @@ function getColorForLevel(level, name) return "" + name + ""; case "Moderator": case "Warning": + case "Report": return "" + name + ""; case "Administrator": return "" + name + ""; diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index 6f13da132..2d3e54f80 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Linq; using SharedLibrary; using SharedLibrary.Network; using System.Threading.Tasks; @@ -659,37 +660,27 @@ namespace SharedLibrary.Commands await E.Target.Tell("[^3" + E.Target.Name + "^7]"); StringBuilder message = new StringBuilder(); - List playerAliases = E.Owner.getPlayerAliases(E.Target); + var playerAliases = E.Owner.GetAliases(E.Target); message.Append("Aliases: "); - foreach (Player P in playerAliases) + var names = new List(); + var ips = new List(); + + foreach (var alias in playerAliases) { - foreach (String S in P.Alias.Names) - { - if (S != String.Empty && S != E.Target.Name) - message.Append(S + " | "); - } + names.AddRange(alias.Names); + ips.AddRange(alias.IPS); } + message.Append(String.Join(" | ", names.Distinct())); + await E.Origin.Tell(message.ToString()); - message = new StringBuilder(); + message.Clear(); + message.Append("IPs: "); + message.Append(String.Join(" | ", ips.Distinct())); - if (E.Target.Alias.IPS != null) - { - message.Append("IPs: "); - - foreach (Player P2 in playerAliases) - { - foreach (String IP in P2.Alias.IPS) - { - if (IP.Split('.').Length > 3 && IP != String.Empty && !message.ToString().Contains(IP)) - message.Append (IP + " | "); - } - } - - await E.Origin.Tell(message.ToString()); - } + await E.Origin.Tell(message.ToString()); } } diff --git a/SharedLibrary/Database.cs b/SharedLibrary/Database.cs index bbbb0e454..4b971cda3 100644 --- a/SharedLibrary/Database.cs +++ b/SharedLibrary/Database.cs @@ -236,7 +236,8 @@ namespace SharedLibrary public List GetRecentPlayers() { List returnssss = new List(); - String Query = String.Format($"SELECT * FROM CLIENTS LIMIT 15 OFFSET (SELECT COUNT(*) FROM CLIENTS)-15"); + //String Query = String.Format($"SELECT * FROM CLIENTS LIMIT 15 OFFSET (SELECT COUNT(*) FROM CLIENTS)-15"); + String Query = "SELECT * FROM CLIENTS ORDER BY LastConnection DESC LIMIT 25"; DataTable Result = GetDataTable(Query); if (Result != null && Result.Rows.Count > 0) diff --git a/SharedLibrary/Interfaces/IManager.cs b/SharedLibrary/Interfaces/IManager.cs index e56afa0bb..412014fdc 100644 --- a/SharedLibrary/Interfaces/IManager.cs +++ b/SharedLibrary/Interfaces/IManager.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace SharedLibrary.Interfaces { diff --git a/SharedLibrary/RCON.cs b/SharedLibrary/RCON.cs index 0defa3faa..ca9508390 100644 --- a/SharedLibrary/RCON.cs +++ b/SharedLibrary/RCON.cs @@ -38,6 +38,8 @@ namespace SharedLibrary.Network String npID = responseLine.Substring(29, 17).Trim(); // DONT TOUCH PLZ int.TryParse(playerInfo[0], out cID); String cIP = responseLine.Substring(72, 20).Trim().Split(':')[0]; + if (cIP.Split(' ').Count() > 1) + cIP = cIP.Split(' ')[1]; Player P = new Player(cName, npID, cID, cIP) { Ping = Ping }; StatusPlayers.Add(P); } diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index 22386dc09..3ca22091e 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -219,7 +219,7 @@ namespace SharedLibrary public async Task Broadcast(String Message) { #if DEBUG - return; + // return; #endif await this.ExecuteCommandAsync($"sayraw {Message}"); } @@ -232,8 +232,8 @@ namespace SharedLibrary public async Task Tell(String Message, Player Target) { #if DEBUG - if (!Target.lastEvent.Remote) - return; + //if (!Target.lastEvent.Remote) + // return; #endif if (Target.ClientID > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console && !Target.lastEvent.Remote) await this.ExecuteCommandAsync($"tellraw {Target.ClientID} {Message}^7"); diff --git a/Stats Plugin/Plugin.cs b/Stats Plugin/Plugin.cs index 92e980cad..74b5e95a4 100644 --- a/Stats Plugin/Plugin.cs +++ b/Stats Plugin/Plugin.cs @@ -18,6 +18,12 @@ namespace StatsPlugin String statLine; PlayerStats pStats; + if (E.Data.Length > 0 && E.Target == null) + { + await E.Origin.Tell("Cannot find the player you specified"); + return; + } + if (E.Target != null) { pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.GetStats(E.Target); @@ -36,8 +42,13 @@ namespace StatsPlugin await E.Owner.Broadcast($"Stats for ^5{name}^7"); await E.Owner.Broadcast(statLine); } + else + { + if (E.Target != null) + await E.Origin.Tell($"Stats for ^5{E.Target.Name}^7"); await E.Origin.Tell(statLine); + } } } @@ -61,6 +72,7 @@ namespace StatsPlugin } } + public class CResetStats : Command { public CResetStats() : base("resetstats", "reset your stats to factory-new, !syntax !resetstats", "rs", Player.Permission.User, 0, false) { } @@ -70,8 +82,8 @@ namespace StatsPlugin var stats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.GetStats(E.Origin); stats.Deaths = 0; stats.Kills = 0; - stats.scorePerMinute = 0.0; - stats.Skill = 0; + stats.scorePerMinute = 1.0; + stats.Skill = 1; stats.KDR = 0.0; await Task.Run(() => { Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.UpdateStats(E.Origin, stats); }); await E.Origin.Tell("Your stats have been reset"); @@ -141,8 +153,11 @@ namespace StatsPlugin if (E.Type == Event.GType.Start) { statLists.Add(new StatTracking(S.getPort())); - S.Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", statLists.Find(c => c.Port == S.getPort()).playerStats.GetTotalPlaytime().ToString("#,##0").ToString)); - S.Manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", statLists.Find(c => c.Port == S.getPort()).playerStats.GetTotalKills().ToString("#,##0").ToString)); + if (statLists.Count == 1) + { + S.Manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", GetTotalKills)); + S.Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", GetTotalPlaytime)); + } } if (E.Type == Event.GType.Stop) @@ -200,15 +215,13 @@ namespace StatsPlugin curServer.lastKill[E.Origin.ClientID] = DateTime.Now; curServer.Kills[E.Origin.ClientID]++; - if ((curServer.lastKill[E.Origin.ClientID] - DateTime.Now).TotalSeconds > 60) - curServer.inactiveMinutes[E.Origin.ClientID]++; + if ((DateTime.Now - curServer.lastKill[E.Origin.ClientID]).TotalSeconds > 120) + curServer.inactiveMinutes[E.Origin.ClientID] += 2; killerStats.Kills++; - if (killerStats.Deaths == 0) - killerStats.KDR = killerStats.Kills; - else - killerStats.KDR = Math.Round((double)killerStats.Kills / (double)killerStats.Deaths, 2); + killerStats.KDR = (killerStats.Deaths == 0) ? killerStats.Kills : killerStats.KDR = Math.Round((double)killerStats.Kills / (double)killerStats.Deaths, 2); + curServer.playerStats.UpdateStats(Killer, killerStats); @@ -228,7 +241,7 @@ namespace StatsPlugin PlayerStats victimStats = curServer.playerStats.GetStats(Victim); victimStats.Deaths++; - victimStats.KDR = Math.Round((double)victimStats.Kills / (double)victimStats.Deaths, 2); + victimStats.KDR = Math.Round(victimStats.Kills / (double)victimStats.Deaths, 2); curServer.playerStats.UpdateStats(Victim, victimStats); @@ -239,6 +252,22 @@ namespace StatsPlugin } } + public static string GetTotalKills() + { + long Kills = 0; + foreach (var S in statLists) + Kills += S.playerStats.GetTotalServerKills(); + return Kills.ToString("#,##0"); + } + + public static string GetTotalPlaytime() + { + long Playtime = 0; + foreach (var S in statLists) + Playtime += S.playerStats.GetTotalServerPlaytime(); + return Playtime.ToString("#,##0"); + } + private void CalculateAndSaveSkill(Player P, StatTracking curServer) { if (P == null) @@ -268,9 +297,9 @@ namespace StatsPlugin // calculate the weight of the new play time againmst lifetime playtime // - double SPMAgainstPlayWeight = newPlayTime / Math.Min(600, DisconnectingPlayerStats.TotalPlayTime); + double SPMAgainstPlayWeight = newPlayTime / Math.Min(600, DisconnectingPlayerStats.TotalPlayTime + newPlayTime); // calculate the new weight against average times the weight against play time - double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight; + double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight * SessionSPM; // if the weight is greater than 1, add, else subtract DisconnectingPlayerStats.scorePerMinute += (SPMWeightAgainstAverage >= 1) ? newSkillFactor : -newSkillFactor; @@ -371,16 +400,16 @@ namespace StatsPlugin } } - public int GetTotalKills() + public long GetTotalServerKills() { var Result = GetDataTable("SELECT SUM(KILLS) FROM STATS"); - return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt32(Result.Rows[0][0]); + return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt64(Result.Rows[0][0]); } - public int GetTotalPlaytime() + public long GetTotalServerPlaytime() { var Result = GetDataTable("SELECT SUM(PLAYTIME) FROM STATS"); - return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt32(Result.Rows[0][0]) / 60; + return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt64(Result.Rows[0][0]) / 60; } public void UpdateStats(Player P, PlayerStats S) @@ -390,8 +419,8 @@ namespace StatsPlugin { "KILLS", S.Kills }, { "DEATHS", S.Deaths }, { "KDR", Math.Round(S.KDR, 2) }, - { "SKILL", Math.Round(S.Skill, 1) }, - { "SPM", Math.Round(S.scorePerMinute, 1) }, + { "SKILL", Math.Round(S.Skill, 2) }, + { "SPM", Math.Round(S.scorePerMinute, 2) }, { "PLAYTIME", S.TotalPlayTime } }; Update("STATS", updatedPlayer, new KeyValuePair("npID", P.NetworkID));