From 04df8d540805b273e5f9818f723549473b986af4 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 1 Jun 2017 12:42:28 -0500 Subject: [PATCH] tweaks to stats and fixed the alias command, made the logger thread safe.. whoops --- Admin/Logger.cs | 10 +++- Admin/Main.cs | 4 +- Admin/Server.cs | 12 +++- Admin/WebService.cs | 13 +++-- Admin/lib/SharedLibrary.dll | Bin 96768 -> 96768 bytes Admin/webfront/header.html | 2 + SharedLibrary/Commands/NativeCommands.cs | 37 +++++-------- SharedLibrary/Database.cs | 3 +- SharedLibrary/Interfaces/IManager.cs | 6 +- SharedLibrary/RCON.cs | 2 + SharedLibrary/Server.cs | 6 +- Stats Plugin/Plugin.cs | 67 ++++++++++++++++------- 12 files changed, 99 insertions(+), 63 deletions(-) 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 d3567c03102310cb12b14402ee667d09595c1d2a..1054f502d0f73c5de9b813df058f5b30535103dd 100644 GIT binary patch delta 33866 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 delta 33339 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 TU+_Xx)4iTK@;kY@iRJ$TYqKM0 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));