diff --git a/Admin/Manager.cs b/Admin/Manager.cs index 56014d90..ac72bff7 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -22,6 +22,7 @@ namespace IW4MAdmin Database AliasesDatabase; SharedLibrary.Interfaces.IPenaltyList ClientPenalties; List Commands; + List MessageTokens; Kayak.IScheduler webServiceTask; Thread WebThread; public SharedLibrary.Interfaces.ILogger Logger { get; private set; } @@ -38,6 +39,7 @@ namespace IW4MAdmin Servers = new List(); Commands = new List(); TaskStatuses = new List(); + MessageTokens = new List(); ClientDatabase = new ClientsDB("Database/clients.rm"); AliasesDatabase = new AliasesDB("Database/aliases.rm"); @@ -106,6 +108,7 @@ namespace IW4MAdmin { Name = "Web Thread" }; + WebThread.Start(); Running = true; @@ -162,5 +165,10 @@ namespace IW4MAdmin { return Logger; } + + public IList GetMessageTokens() + { + return MessageTokens; + } } } diff --git a/Admin/PenaltyList.cs b/Admin/PenaltyList.cs index cc7ebc6c..d6c96913 100644 --- a/Admin/PenaltyList.cs +++ b/Admin/PenaltyList.cs @@ -20,7 +20,7 @@ namespace IW4MAdmin public void RemovePenalty(Penalty P) { - Manager.GetInstance().GetClientDatabase().RemoveBan(P.npID); + Manager.GetInstance().GetClientDatabase().RemoveBan(P.OffenderID); } public List FindPenalties(Player P) diff --git a/Admin/Server.cs b/Admin/Server.cs index fabac6d4..ed554c55 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -40,7 +40,7 @@ namespace IW4MAdmin if (Origin == null) return allAliases; - Aliases currentIdentityAliases = Manager.GetAliasesDatabase().GetPlayerAliases(Origin.databaseID); + Aliases currentIdentityAliases = Manager.GetAliasesDatabase().GetPlayerAliases(Origin.DatabaseID); if (currentIdentityAliases == null) return allAliases; @@ -51,50 +51,50 @@ namespace IW4MAdmin override public async Task AddPlayer(Player P) { - if (P.clientID < 0 || P.clientID > (Players.Count-1) || P.Ping < 1 || P.Ping == 999) // invalid index + if (P.ClientID < 0 || P.ClientID > (Players.Count-1) || P.Ping < 1 || P.Ping == 999) // invalid index return false; - if (Players[P.clientID] != null && Players[P.clientID].npID == P.npID) // if someone has left and a new person has taken their spot between polls + if (Players[P.ClientID] != null && Players[P.ClientID].NetworkID == P.NetworkID) // if someone has left and a new person has taken their spot between polls { // update their ping - Players[P.clientID].Ping = P.Ping; + Players[P.ClientID].Ping = P.Ping; return true; } - Logger.WriteDebug($"Client slot #{P.clientID} now reserved"); + Logger.WriteDebug($"Client slot #{P.ClientID} now reserved"); try { - Player NewPlayer = Manager.GetClientDatabase().GetPlayer(P.npID, P.clientID); + Player NewPlayer = Manager.GetClientDatabase().GetPlayer(P.NetworkID, P.ClientID); if (NewPlayer == null) // first time connecting { - Logger.WriteDebug($"Client slot #{P.clientID} first time connecting"); + Logger.WriteDebug($"Client slot #{P.ClientID} first time connecting"); Manager.GetClientDatabase().AddPlayer(P); - NewPlayer = Manager.GetClientDatabase().GetPlayer(P.npID, P.clientID); - Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.databaseID, NewPlayer.Name, NewPlayer.IP)); + NewPlayer = Manager.GetClientDatabase().GetPlayer(P.NetworkID, P.ClientID); + Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.DatabaseID, NewPlayer.Name, NewPlayer.IP)); } List Admins = Manager.GetClientDatabase().GetAdmins(); if (Admins.Find(x => x.Name == P.Name) != null) { - if ((Admins.Find(x => x.Name == P.Name).npID != P.npID) && NewPlayer.Level < Player.Permission.Moderator) - await this.ExecuteCommandAsync("clientkick " + P.clientID + " \"Please do not impersonate an admin^7\""); + if ((Admins.Find(x => x.Name == P.Name).NetworkID != P.NetworkID) && NewPlayer.Level < Player.Permission.Moderator) + await this.ExecuteCommandAsync("clientkick " + P.ClientID + " \"Please do not impersonate an admin^7\""); } // below this needs to be optimized ~ 425ms runtime NewPlayer.updateName(P.Name.Trim()); - NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.databaseID); + NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.DatabaseID); if (NewPlayer.Alias == null) { - Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.databaseID, NewPlayer.Name, NewPlayer.IP)); - NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.databaseID); + Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.DatabaseID, NewPlayer.Name, NewPlayer.IP)); + NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.DatabaseID); } if (P.lastEvent == null || P.lastEvent.Owner == null) - NewPlayer.lastEvent = new Event(Event.GType.Say, null, NewPlayer, null, this); // this is messy but its throwing an error when they've started it too late + NewPlayer.lastEvent = new Event(Event.GType.Say, null, NewPlayer, null, this); // this is messy but its throwing an error when they've started in too late else NewPlayer.lastEvent = P.lastEvent; @@ -120,7 +120,7 @@ namespace IW4MAdmin if (NewPlayer.Level == Player.Permission.Banned) // their guid is already banned so no need to check aliases { - Logger.WriteInfo($"Banned client {P.Name}::{P.npID} trying to connect..."); + Logger.WriteInfo($"Banned client {P.Name}::{P.NetworkID} trying to connect..."); await NewPlayer.Kick(NewPlayer.lastOffense != null ? "^7Previously banned for ^5 " + NewPlayer.lastOffense : "^7Previous Ban", NewPlayer); return true; @@ -140,19 +140,19 @@ namespace IW4MAdmin if (B != null && B.BType == Penalty.Type.Ban) { - Logger.WriteDebug($"Banned client {aP.Name}::{aP.npID} is connecting with new alias {NewPlayer.Name}"); + Logger.WriteDebug($"Banned client {aP.Name}::{aP.NetworkID} is connecting with new alias {NewPlayer.Name}"); NewPlayer.lastOffense = String.Format("Evading ( {0} )", aP.Name); await NewPlayer.Ban(B.Reason != null ? "^7Previously banned for ^5 " + B.Reason : "^7Previous Ban", NewPlayer); - Players[NewPlayer.clientID] = null; + Players[NewPlayer.ClientID] = null; return true; } } - Players[NewPlayer.clientID] = null; - Players[NewPlayer.clientID] = NewPlayer; - Logger.WriteInfo($"Client {NewPlayer.Name}::{NewPlayer.npID} connecting..."); // they're clean + Players[NewPlayer.ClientID] = null; + Players[NewPlayer.ClientID] = NewPlayer; + Logger.WriteInfo($"Client {NewPlayer.Name}::{NewPlayer.NetworkID} connecting..."); // they're clean // todo: get this out of here while (chatHistory.Count > Math.Ceiling((double)ClientNum / 2)) @@ -168,7 +168,7 @@ namespace IW4MAdmin catch (Exception E) { - Manager.GetLogger().WriteError($"Unable to add player {P.Name}::{P.npID}"); + Manager.GetLogger().WriteError($"Unable to add player {P.Name}::{P.NetworkID}"); Manager.GetLogger().WriteDebug(E.StackTrace); return false; } @@ -183,7 +183,7 @@ namespace IW4MAdmin Leaving.Connections++; Manager.GetClientDatabase().UpdatePlayer(Leaving); - Logger.WriteInfo($"Client {Leaving.Name}::{Leaving.npID} disconnecting..."); + Logger.WriteInfo($"Client {Leaving.Name}::{Leaving.NetworkID} disconnecting..."); await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this)); Players[cNum] = null; @@ -241,6 +241,7 @@ namespace IW4MAdmin override public async Task ValidateCommand(Event E) { string CommandString = E.Data.Substring(1, E.Data.Length - 1).Split(' ')[0]; + E.Message = E.Data; Command C = null; foreach (Command cmd in Manager.GetCommands()) @@ -270,14 +271,11 @@ namespace IW4MAdmin throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\""); } - if (C.needsTarget) + if (C.needsTarget || Args.Length > 0) { int cNum = -1; int.TryParse(Args[0], out cNum); - // this is so ugly wtf is it doing here? - if (C.Name == "stats" && Args.Length == 1) - E.Target = E.Origin; if (Args[0] == String.Empty) return C; @@ -346,7 +344,7 @@ namespace IW4MAdmin for (int i = 0; i < Players.Count; i++) { - if (CurrentPlayers.Find(p => p.clientID == i) == null && Players[i] != null) + if (CurrentPlayers.Find(p => p.ClientID == i) == null && Players[i] != null) await RemovePlayer(i); } @@ -397,8 +395,7 @@ namespace IW4MAdmin if (lastMessage.TotalSeconds > messageTime && messages.Count > 0 && Players.Count > 0) { - initMacros(); // somethings dynamically change so we have to re-init the dictionary - await Broadcast(Utilities.LoadMacro(Macros, messages[nextMessage])); + await Broadcast(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), messages[nextMessage])); if (nextMessage == (messages.Count - 1)) nextMessage = 0; else @@ -653,7 +650,7 @@ namespace IW4MAdmin await Target.Kick("Too many warnings!", Origin); else { - Penalty newPenalty = new Penalty(Penalty.Type.Warning, Reason.StripColors(), Target.npID, Origin.npID, DateTime.Now, Target.IP); + Penalty newPenalty = new Penalty(Penalty.Type.Warning, Reason.StripColors(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP); Manager.GetClientPenalties().AddPenalty(newPenalty); Target.Warnings++; String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", Target.Warnings, Target.Name, Target.lastOffense); @@ -663,21 +660,21 @@ namespace IW4MAdmin public override async Task Kick(String Reason, Player Target, Player Origin) { - if (Target.clientID > -1) + if (Target.ClientID > -1) { String Message = "^1Player Kicked: ^5" + Reason; - Penalty newPenalty = new Penalty(Penalty.Type.Kick, Reason.StripColors().Trim(), Target.npID, Origin.npID, DateTime.Now, Target.IP); + Penalty newPenalty = new Penalty(Penalty.Type.Kick, Reason.StripColors().Trim(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP); Manager.GetClientPenalties().AddPenalty(newPenalty); - await this.ExecuteCommandAsync("clientkick " + Target.clientID + " \"" + Message + "^7\""); + await this.ExecuteCommandAsync("clientkick " + Target.ClientID + " \"" + Message + "^7\""); } } public override async Task TempBan(String Reason, Player Target, Player Origin) { - if (Target.clientID > -1) + if (Target.ClientID > -1) { - await this.ExecuteCommandAsync($"tempbanclient {Target.clientID } \"^1Player Temporarily Banned: ^5{ Reason } (1 hour)\""); - Penalty newPenalty = new Penalty(Penalty.Type.TempBan, Reason.StripColors(), Target.npID, Origin.npID, DateTime.Now, Target.IP); + await this.ExecuteCommandAsync($"tempbanclient {Target.ClientID } \"^1Player Temporarily Banned: ^5{ Reason } (1 hour)\""); + Penalty newPenalty = new Penalty(Penalty.Type.TempBan, Reason.StripColors(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP); await Task.Run(() => { Manager.GetClientPenalties().AddPenalty(newPenalty); @@ -696,7 +693,7 @@ namespace IW4MAdmin { Logger.WriteError("Ban target is null"); Logger.WriteDebug($"Message: {Message}"); - Logger.WriteDebug($"Origin: {Origin.Name}::{Origin.npID}"); + Logger.WriteDebug($"Origin: {Origin.Name}::{Origin.NetworkID}"); return; } @@ -705,16 +702,16 @@ namespace IW4MAdmin { if (server.getPlayers().Count > 0) { - var activeClient = server.getPlayers().Find(x => x.npID == Target.npID); + var activeClient = server.getPlayers().Find(x => x.NetworkID == Target.NetworkID); if (activeClient != null) - await server.ExecuteCommandAsync("tempbanclient " + activeClient.clientID + " \"" + Message + "^7" + GetWebsiteString() + "^7\""); + await server.ExecuteCommandAsync("tempbanclient " + activeClient.ClientID + " \"" + Message + "^7" + GetWebsiteString() + "^7\""); } } if (Origin != null) { Target.setLevel(Player.Permission.Banned); - Penalty newBan = new Penalty(Penalty.Type.Ban, Target.lastOffense, Target.npID, Origin.npID, DateTime.Now, Target.IP); + Penalty newBan = new Penalty(Penalty.Type.Ban, Target.lastOffense, Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP); await Task.Run(() => { @@ -727,14 +724,14 @@ namespace IW4MAdmin List toRemove = new List(); foreach (Report R in Reports) { - if (R.Target.npID == Target.npID) + if (R.Target.NetworkID == Target.NetworkID) toRemove.Add(R); } foreach (Report R in toRemove) { Reports.Remove(R); - Logger.WriteInfo("Removing report for banned GUID - " + R.Origin.npID); + Logger.WriteInfo("Removing report for banned GUID - " + R.Origin.NetworkID); } } } @@ -753,7 +750,7 @@ namespace IW4MAdmin Manager.GetClientPenalties().RemovePenalty(PenaltyToRemove); - Player P = Manager.GetClientDatabase().GetPlayer(Target.npID, -1); + Player P = Manager.GetClientDatabase().GetPlayer(Target.NetworkID, -1); P.setLevel(Player.Permission.User); Manager.GetClientDatabase().UpdatePlayer(P); }); @@ -789,10 +786,8 @@ namespace IW4MAdmin override public void initMacros() { - Macros = new Dictionary(); - Macros.Add("TOTALPLAYERS", Manager.GetClientDatabase().TotalPlayers()); - Macros.Add("TOTALKILLS", totalKills); - Macros.Add("VERSION", IW4MAdmin.Program.Version); + Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYERS", Manager.GetClientDatabase().TotalPlayers().ToString)); + Manager.GetMessageTokens().Add(new MessageToken("VERSION", Program.Version.ToString)); } override public void initCommands() diff --git a/Admin/WebService.cs b/Admin/WebService.cs index 8169ca52..b1cc1048 100644 --- a/Admin/WebService.cs +++ b/Admin/WebService.cs @@ -196,7 +196,7 @@ namespace IW4MAdmin foreach (Player P in S.getPlayers()) { PlayerInfo pInfo = new PlayerInfo(); - pInfo.playerID = P.databaseID; + pInfo.playerID = P.DatabaseID; pInfo.playerName = P.Name; pInfo.playerLevel = P.Level.ToString(); eachServer.players.Add(pInfo); @@ -366,8 +366,8 @@ namespace IW4MAdmin foreach (var p in selectedPenalties) { - Player admin = Manager.GetInstance().GetClientDatabase().GetPlayer(p.bannedByID, 0); - Player penalized = Manager.GetInstance().GetClientDatabase().GetPlayer(p.npID, 0); + Player admin = Manager.GetInstance().GetClientDatabase().GetPlayer(p.PenaltyOriginID, 0); + Player penalized = Manager.GetInstance().GetClientDatabase().GetPlayer(p.OffenderID, 0); if (admin == null && penalized == null) continue; if (admin == null) @@ -379,8 +379,8 @@ namespace IW4MAdmin pInfo.penaltyTime = SharedLibrary.Utilities.timePassed(p.When); pInfo.penaltyType = p.BType.ToString(); pInfo.playerName = penalized.Name; - pInfo.playerID = penalized.databaseID; - if (admin.npID == penalized.npID) + pInfo.playerID = penalized.DatabaseID; + if (admin.NetworkID == penalized.NetworkID) { pInfo.adminName = "IW4MAdmin"; pInfo.adminLevel = Player.Permission.Console.ToString(); @@ -621,11 +621,11 @@ namespace IW4MAdmin var playerAliases = Manager.GetInstance().Servers.First().GetAliases(pp); PlayerInfo eachPlayer = new PlayerInfo(); - eachPlayer.playerID = pp.databaseID; + eachPlayer.playerID = pp.DatabaseID; eachPlayer.playerIP = pp.IP; eachPlayer.playerLevel = pp.Level.ToString(); eachPlayer.playerName = pp.Name; - eachPlayer.playernpID = pp.npID; + eachPlayer.playernpID = pp.NetworkID; eachPlayer.forumID = -1; eachPlayer.authed = authed; eachPlayer.showV2Features = false; diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index 3f115761..d3567c03 100644 Binary files a/Admin/lib/SharedLibrary.dll and b/Admin/lib/SharedLibrary.dll differ diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index 2fff0fed..6f13da13 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -7,9 +7,9 @@ using System.Threading.Tasks; namespace SharedLibrary.Commands { - class Quit : Command + class CQuit : Command { - public Quit(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CQuit(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -36,9 +36,9 @@ namespace SharedLibrary.Commands } } - class Warn : Command + class Cwarn : Command { - public Warn(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public Cwarn(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -50,9 +50,9 @@ namespace SharedLibrary.Commands } } - class WarnClear : Command + class CWarnClear : Command { - public WarnClear(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CWarnClear(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -63,9 +63,9 @@ namespace SharedLibrary.Commands } } - class Kick : Command + class CKick : Command { - public Kick(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CKick(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -77,9 +77,9 @@ namespace SharedLibrary.Commands } } - class Say : Command + class CSay : Command { - public Say(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CSay(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -87,16 +87,19 @@ namespace SharedLibrary.Commands } } - class TempBan : Command + class CTempBan : Command { - public TempBan(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CTempBan(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { E.Target.lastOffense = SharedLibrary.Utilities.RemoveWords(E.Data, 1); String Message = E.Target.lastOffense; if (E.Origin.Level > E.Target.Level) + { await E.Target.TempBan(Message, E.Origin); + await E.Origin.Tell($"Successfully temp banned {E.Target.Name}"); + } else await E.Origin.Tell("You cannot temp ban " + E.Target.Name); } @@ -118,7 +121,7 @@ namespace SharedLibrary.Commands if (E.Origin.Level > E.Target.Level) { await E.Target.Ban(Message, E.Origin); - await E.Origin.Tell(String.Format("Sucessfully banned ^5{0} ^7({1})", E.Target.Name, E.Target.npID)); + await E.Origin.Tell(String.Format("Sucessfully banned ^5{0} ^7({1})", E.Target.Name, E.Target.NetworkID)); } else await E.Origin.Tell("You cannot ban " + E.Target.Name); @@ -132,7 +135,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { await E.Owner.Unban(E.Target); - await E.Origin.Tell($"Successfully unbanned {E.Target.Name}::{E.Target.npID}"); + await E.Origin.Tell($"Successfully unbanned {E.Target.Name}::{E.Target.NetworkID}"); } } @@ -142,7 +145,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.clientID, E.Origin.npID, E.Origin.databaseID, SharedLibrary.Utilities.levelToColor(E.Origin.Level), E.Origin.IP); + String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, SharedLibrary.Utilities.levelToColor(E.Origin.Level), E.Origin.IP); await E.Origin.Tell(You); } } @@ -163,9 +166,9 @@ namespace SharedLibrary.Commands continue; if (P.Masked) - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(Player.Permission.User), P.clientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(Player.Permission.User), P.ClientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); else - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(P.Level), P.clientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(P.Level), P.ClientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); if (count == 2 || E.Owner.getPlayers().Count == 1) { @@ -217,7 +220,10 @@ namespace SharedLibrary.Commands helpResponse.Append(" [^3" + C.Name + "^7] "); if (count >= 4) { - await E.Origin.Tell(helpResponse.ToString()); + if (E.Message[0] == '@') + await E.Owner.Broadcast(helpResponse.ToString()); + else + await E.Origin.Tell(helpResponse.ToString()); helpResponse = new StringBuilder(); count = 0; } @@ -288,7 +294,7 @@ namespace SharedLibrary.Commands { foreach (var player in server.getPlayers()) { - if (player != null && player.npID == E.Target.npID) + if (player != null && player.NetworkID == E.Target.NetworkID) { player.setLevel(newPerm); await E.Target.Tell("Congratulations! You have been promoted to ^3" + newPerm); @@ -341,7 +347,12 @@ namespace SharedLibrary.Commands { var P = E.Owner.Players[i]; if (P != null && P.Level > Player.Permission.Flagged && !P.Masked) - await E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); + { + if (E.Message[0] == '@') + await E.Owner.Broadcast(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); + else + await E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); + } } } } @@ -386,7 +397,7 @@ namespace SharedLibrary.Commands foreach (Player P in db_players) { - String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.Name, P.databaseID, SharedLibrary.Utilities.levelToColor(P.Level), P.IP, P.getLastConnection()); + String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.Name, P.DatabaseID, SharedLibrary.Utilities.levelToColor(P.Level), P.IP, P.getLastConnection()); await E.Origin.Tell(mesg); } } @@ -431,7 +442,7 @@ namespace SharedLibrary.Commands if (Current != null) { - String mesg = String.Format("^1{0} ^7now goes by ^5{1}^7 [^3{2}^7]", lookingFor, Current.Name, Current.databaseID); + String mesg = String.Format("^1{0} ^7now goes by ^5{1}^7 [^3{2}^7]", lookingFor, Current.Name, Current.DatabaseID); await E.Origin.Tell(mesg); } } @@ -445,11 +456,22 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { if (E.Owner.rules.Count < 1) - await E.Origin.Tell("The server onwer has not set any rules."); + { + if (E.Message.IsBroadcastCommand()) + await E.Owner.Broadcast("The server owner has not set any rules."); + else + await E.Origin.Tell("The server owner has not set any rules."); + } + else { foreach (String r in E.Owner.rules) - await E.Origin.Tell("- " + r); + { + if (E.Message.IsBroadcastCommand()) + await E.Owner.Broadcast("- " + r); + else + await E.Origin.Tell("- " + r); + } } } } @@ -479,9 +501,9 @@ namespace SharedLibrary.Commands } } - class Flag : Command + class CFlag : Command { - public Flag(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + public CFlag(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) { @@ -499,7 +521,9 @@ namespace SharedLibrary.Commands else { + E.Data = Utilities.RemoveWords(E.Data, 1); E.Target.setLevel(Player.Permission.Flagged); + E.Owner.Manager.GetClientPenalties().AddPenalty(new Penalty(Penalty.Type.Flag, E.Data, E.Target.NetworkID, E.Origin.NetworkID, DateTime.Now, E.Target.IP)); await E.Origin.Tell("You have ^5flagged ^7" + E.Target.Name); } @@ -513,7 +537,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - if (E.Owner.Reports.Find(x => (x.Origin == E.Origin && x.Target.npID == E.Target.npID)) != null) + if (E.Owner.Reports.Find(x => (x.Origin == E.Origin && x.Target.NetworkID == E.Target.NetworkID)) != null) { await E.Origin.Tell("You have already reported this player"); return; @@ -606,7 +630,7 @@ namespace SharedLibrary.Commands return; } - Player Banner = E.Owner.Manager.GetClientDatabase().GetPlayer(BannedPenalty.bannedByID, -1); + Player Banner = E.Owner.Manager.GetClientDatabase().GetPlayer(BannedPenalty.PenaltyOriginID, -1); if (Banner == null) { @@ -624,7 +648,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.Alias = E.Owner.Manager.GetAliasesDatabase().GetPlayerAliases(E.Target.databaseID); + E.Target.Alias = E.Owner.Manager.GetAliasesDatabase().GetPlayerAliases(E.Target.DatabaseID); if (E.Target.Alias == null) { @@ -675,7 +699,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - await E.Origin.currentServer.ExecuteCommandAsync(E.Data.Trim()); + await E.Owner.ExecuteCommandAsync(E.Data.Trim()); await E.Origin.Tell("Successfuly sent RCON command!"); } } diff --git a/SharedLibrary/Database.cs b/SharedLibrary/Database.cs index d616eb2c..bbbb0e45 100644 --- a/SharedLibrary/Database.cs +++ b/SharedLibrary/Database.cs @@ -440,7 +440,7 @@ namespace SharedLibrary public List GetClientPenalties(Player P) { List ClientPenalties = new List(); - String Query = $"SELECT * FROM `BANS` WHERE `npID` = '{P.npID}' OR `IP` = '{P.IP}'"; + String Query = $"SELECT * FROM `BANS` WHERE `npID` = '{P.NetworkID}' OR `IP` = '{P.IP}'"; DataTable Result = GetDataTable(Query); foreach (DataRow Row in Result.Rows) @@ -509,7 +509,7 @@ namespace SharedLibrary Dictionary newPlayer = new Dictionary { { "Name", Utilities.removeNastyChars(P.Name) }, - { "npID", P.npID }, + { "npID", P.NetworkID }, { "Level", (int)P.Level }, { "LastOffense", "" }, { "Connections", 1 }, @@ -527,7 +527,7 @@ namespace SharedLibrary Dictionary updatedPlayer = new Dictionary { { "Name", P.Name }, - { "npID", P.npID }, + { "npID", P.NetworkID }, { "Level", (int)P.Level }, { "LastOffense", P.lastOffense }, { "Connections", P.Connections }, @@ -536,7 +536,7 @@ namespace SharedLibrary { "UID", P.UID }, { "Masked", Convert.ToInt32(P.Masked) } }; - Update("CLIENTS", updatedPlayer, new KeyValuePair("npID", P.npID)); + Update("CLIENTS", updatedPlayer, new KeyValuePair("npID", P.NetworkID)); } @@ -546,8 +546,8 @@ namespace SharedLibrary Dictionary newBan = new Dictionary { { "Reason", Utilities.removeNastyChars(B.Reason) }, - { "npID", B.npID }, - { "bannedByID", B.bannedByID }, + { "npID", B.OffenderID }, + { "bannedByID", B.PenaltyOriginID }, { "IP", B.IP }, { "TIME", Utilities.DateTimeSQLite(DateTime.Now) }, { "TYPE", B.BType } diff --git a/SharedLibrary/Event.cs b/SharedLibrary/Event.cs index 9ef2130c..4e3f6241 100644 --- a/SharedLibrary/Event.cs +++ b/SharedLibrary/Event.cs @@ -125,7 +125,7 @@ namespace SharedLibrary { Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]"); string message = rgx.Replace(line[4], ""); - return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromEventLine(line, 2), null, SV); + return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromEventLine(line, 2), null, SV) { Message = Utilities.removeNastyChars(message) }; } if (eventType == ":") @@ -149,6 +149,7 @@ namespace SharedLibrary public GType Type; public string Data; // Data is usually the message sent by player + public string Message; public Player Origin; public Player Target; public Server Owner; diff --git a/SharedLibrary/Interfaces/IManager.cs b/SharedLibrary/Interfaces/IManager.cs index 74725bee..e56afa0b 100644 --- a/SharedLibrary/Interfaces/IManager.cs +++ b/SharedLibrary/Interfaces/IManager.cs @@ -17,5 +17,6 @@ namespace SharedLibrary.Interfaces IPenaltyList GetClientPenalties(); ClientsDB GetClientDatabase(); AliasesDB GetAliasesDatabase(); + IList GetMessageTokens(); } } diff --git a/SharedLibrary/MessageToken.cs b/SharedLibrary/MessageToken.cs new file mode 100644 index 00000000..718e2346 --- /dev/null +++ b/SharedLibrary/MessageToken.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary +{ + public class MessageToken + { + public string Name { get; private set; } + Func Value; + public MessageToken(string Name, Func Value) + { + this.Name = Name; + this.Value = Value; + } + + public override string ToString() + { + return Value().ToString(); + } + } +} diff --git a/SharedLibrary/Penalty.cs b/SharedLibrary/Penalty.cs index ac5b1a33..690645ec 100644 --- a/SharedLibrary/Penalty.cs +++ b/SharedLibrary/Penalty.cs @@ -10,8 +10,8 @@ namespace SharedLibrary public Penalty(Type BType, String Reas, String TargID, String From, DateTime time, String ip) { Reason = Reas.Replace("!",""); - npID = TargID; - bannedByID = From; + OffenderID = TargID; + PenaltyOriginID = From; When = time; IP = ip; this.BType = BType; @@ -24,15 +24,17 @@ namespace SharedLibrary public enum Type { + Report, Warning, + Flag, Kick, TempBan, Ban } public String Reason { get; private set; } - public String npID { get; private set; } - public String bannedByID { get; private set; } + public String OffenderID { get; private set; } + public String PenaltyOriginID { get; private set; } public DateTime When { get; private set; } public String IP { get; private set; } public Type BType { get; private set; } diff --git a/SharedLibrary/Player.cs b/SharedLibrary/Player.cs index 2fb28374..4d56e9da 100644 --- a/SharedLibrary/Player.cs +++ b/SharedLibrary/Player.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Linq; using System.Threading.Tasks; @@ -38,7 +37,7 @@ namespace SharedLibrary public override bool Equals(object obj) { - return ((Player)obj).npID == this.npID; + return ((Player)obj).NetworkID == NetworkID; } public override int GetHashCode() @@ -49,8 +48,8 @@ namespace SharedLibrary public Player(string n, string id, int num, int l) { Name = n; - npID = id; - clientID = num; + NetworkID = id; + ClientID = num; Level = (Player.Permission)l; lastOffense = String.Empty; Connections = 0; @@ -64,8 +63,8 @@ namespace SharedLibrary public Player(string n, string id, int num, String I) { Name = n; - npID = id; - clientID = num; + NetworkID = id; + ClientID = num; IP = I; LastConnection = DateTime.Now; } @@ -73,20 +72,20 @@ namespace SharedLibrary public Player(String n, String id, Player.Permission P, String I, String UID) { Name = n; - npID = id; + NetworkID = id; Level = P; IP = I; - clientID = -1; + ClientID = -1; this.UID = UID; } public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2) { Name = n; - npID = id; - clientID = num; + NetworkID = id; + ClientID = num; Level = l; - databaseID = cind; + DatabaseID = cind; if (lo == null) lastOffense = String.Empty; else @@ -101,10 +100,10 @@ namespace SharedLibrary public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2, DateTime LC, string UID, bool masked) { Name = n; - npID = id; - clientID = num; + NetworkID = id; + ClientID = num; Level = l; - databaseID = cind; + DatabaseID = cind; if (lo == null) lastOffense = String.Empty; else @@ -118,12 +117,9 @@ namespace SharedLibrary Masked = masked; } - public bool registerUID(String UID) + public override string ToString() { - if (UID.Length > 5) - this.UID = UID; - - return this.UID == UID; + return $"{Name}::{NetworkID}"; } public String getLastConnection() @@ -142,7 +138,7 @@ namespace SharedLibrary IP = I; } - public void setLevel(Player.Permission Perm) + public void setLevel(Permission Perm) { Level = Perm; } @@ -173,16 +169,14 @@ namespace SharedLibrary } public String Name { get; private set; } - public string npID { get; private set; } - public int clientID { get; private set; } - public Player.Permission Level { get; private set; } - public int databaseID { get; private set; } + public string NetworkID { get; private set; } + public int ClientID { get; private set; } + public Permission Level { get; private set; } + public int DatabaseID { get; private set; } public int Connections { get; set; } public String IP { get; private set; } public String UID { get; private set; } public DateTime LastConnection { get; private set; } - public Server currentServer { get; private set; } - public int Ping; public Event lastEvent; diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index 0fd3668f..22386dc0 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -25,9 +25,7 @@ namespace SharedLibrary Players = new List(new Player[18]); events = new Queue(); - Macros = new Dictionary(); Reports = new List(); - statusPlayers = new Dictionary(); playerHistory = new Queue(); chatHistory = new List(); lastWebChat = DateTime.Now; @@ -44,10 +42,10 @@ namespace SharedLibrary if (owner == null) commands.Add(new Owner("owner", "claim ownership of the server", "owner", Player.Permission.User, 0, false)); - commands.Add(new Quit("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, 0, false)); - commands.Add(new Kick("kick", "kick a player by name. syntax: !kick .", "k", Player.Permission.Trusted, 2, true)); - commands.Add(new Say("say", "broadcast message to all players. syntax: !say .", "s", Player.Permission.Moderator, 1, false)); - commands.Add(new TempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban .", "tb", Player.Permission.Moderator, 2, true)); + commands.Add(new CQuit("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, 0, false)); + commands.Add(new CKick("kick", "kick a player by name. syntax: !kick .", "k", Player.Permission.Trusted, 2, true)); + commands.Add(new CSay("say", "broadcast message to all players. syntax: !say .", "s", Player.Permission.Moderator, 1, false)); + commands.Add(new CTempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban .", "tb", Player.Permission.Moderator, 2, true)); commands.Add(new CBan("ban", "permanently ban a player from the server. syntax: !ban ", "b", Player.Permission.SeniorAdmin, 2, true)); commands.Add(new CWhoAmI("whoami", "give information about yourself. syntax: !whoami.", "who", Player.Permission.User, 0, false)); commands.Add(new CList("list", "list active clients syntax: !list.", "l", Player.Permission.Moderator, 0, false)); @@ -57,15 +55,15 @@ namespace SharedLibrary commands.Add(new CSetLevel("setlevel", "set player to specified administration level. syntax: !setlevel .", "sl", Player.Permission.Owner, 2, true)); commands.Add(new CUsage("usage", "get current application memory usage. syntax: !usage.", "us", Player.Permission.Moderator, 0, false)); commands.Add(new CUptime("uptime", "get current application running time. syntax: !uptime.", "up", Player.Permission.Moderator, 0, false)); - commands.Add(new Warn("warn", "warn player for infringing rules syntax: !warn .", "w", Player.Permission.Trusted, 2, true)); - commands.Add(new WarnClear("warnclear", "remove all warning for a player syntax: !warnclear .", "wc", Player.Permission.Trusted, 1, true)); + commands.Add(new Cwarn("warn", "warn player for infringing rules syntax: !warn .", "w", Player.Permission.Trusted, 2, true)); + commands.Add(new CWarnClear("warnclear", "remove all warning for a player syntax: !warnclear .", "wc", Player.Permission.Trusted, 1, true)); commands.Add(new CUnban("unban", "unban player by database id. syntax: !unban @.", "ub", Player.Permission.SeniorAdmin, 1, true)); commands.Add(new CListAdmins("admins", "list currently connected admins. syntax: !admins.", "a", Player.Permission.User, 0, false)); commands.Add(new CLoadMap("map", "change to specified map. syntax: !map", "m", Player.Permission.Administrator, 1, false)); commands.Add(new CFindPlayer("find", "find player in database. syntax: !find ", "f", Player.Permission.SeniorAdmin, 1, false)); commands.Add(new CListRules("rules", "list server rules. syntax: !rules", "r", Player.Permission.User, 0, false)); commands.Add(new CPrivateMessage("privatemessage", "send message to other player. syntax: !pm ", "pm", Player.Permission.User, 2, true)); - commands.Add(new Flag("flag", "flag a suspicious player and announce to admins on join . syntax !flag :", "flag", Player.Permission.Moderator, 1, true)); + commands.Add(new CFlag("flag", "flag a suspicious player and announce to admins on join . syntax !flag :", "flag", Player.Permission.Moderator, 2, true)); commands.Add(new CReport("report", "report a player for suspicious behaivor. syntax !report ", "rep", Player.Permission.User, 2, true)); commands.Add(new CListReports("reports", "get most recent reports. syntax !reports", "reports", Player.Permission.Moderator, 0, false)); commands.Add(new CMask("mask", "hide your online presence from online admin list. syntax: !mask", "mask", Player.Permission.Administrator, 0, false)); @@ -234,10 +232,11 @@ namespace SharedLibrary public async Task Tell(String Message, Player Target) { #if DEBUG - 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"); + if (Target.ClientID > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console && !Target.lastEvent.Remote) + await this.ExecuteCommandAsync($"tellraw {Target.ClientID} {Message}^7"); if (Target.Level == Player.Permission.Console) { @@ -456,24 +455,15 @@ namespace SharedLibrary protected DateTime lastPoll; protected int nextMessage; - protected Dictionary Macros; protected DateTime lastWebChat; public string Password { get; private set; } public int Handle { get; private set; } protected int PID; protected IFile logFile; - // Will probably move this later - public Dictionary statusPlayers; - public bool isRunning; - // Log stuff protected String Mod; - // Databases - //public ClientsDB clientDB; - //public AliasesDB aliasDB; - //Remote public Queue commandResult = new Queue(); } diff --git a/SharedLibrary/SharedLibrary.csproj b/SharedLibrary/SharedLibrary.csproj index 2aa5b492..50076431 100644 --- a/SharedLibrary/SharedLibrary.csproj +++ b/SharedLibrary/SharedLibrary.csproj @@ -76,6 +76,7 @@ + diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs index d2676f02..869ab047 100644 --- a/SharedLibrary/Utilities.cs +++ b/SharedLibrary/Utilities.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Text; using System.Text.RegularExpressions; +using System.Linq; using System.Collections.Generic; namespace SharedLibrary @@ -120,27 +121,28 @@ namespace SharedLibrary } } - public static String LoadMacro(Dictionary Dict, String str) + public static String ProcessMessageToken(IList tokens, String str) { - MatchCollection Found = Regex.Matches(str, @"\{\{[A-Z]+\}\}", RegexOptions.IgnoreCase); - foreach (Match M in Found) + MatchCollection RegexMatches = Regex.Matches(str, @"\{\{[A-Z]+\}\}", RegexOptions.IgnoreCase); + foreach (Match M in RegexMatches) { String Match = M.Value; String Identifier = M.Value.Substring(2, M.Length - 4); - Dict.TryGetValue(Identifier, out object foundVal); - String Replacement; - if (foundVal != null) - Replacement = foundVal.ToString(); - else - Replacement = ""; + var found = tokens.FirstOrDefault(t => t.Name.ToLower() == Identifier.ToLower()); - str = str.Replace(Match, Replacement); + if (found != null) + str = str.Replace(Match, found.ToString()); } return str; } + public static bool IsBroadcastCommand(this string str) + { + return str[0] == '@'; + } + /// /// Get the full gametype name /// diff --git a/Stats Plugin/Plugin.cs b/Stats Plugin/Plugin.cs index 8ba5c728..92e980ca 100644 --- a/Stats Plugin/Plugin.cs +++ b/Stats Plugin/Plugin.cs @@ -20,27 +20,34 @@ namespace StatsPlugin if (E.Target != null) { - pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.getStats(E.Target); + pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.GetStats(E.Target); statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); } else { - pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.getStats(E.Origin); + pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.GetStats(E.Origin); statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill); } - await E.Origin.Tell(statLine); + if (E.Message.IsBroadcastCommand()) + { + string name = E.Target == null ? E.Origin.Name : E.Target.Name; + await E.Owner.Broadcast($"Stats for ^5{name}^7"); + await E.Owner.Broadcast(statLine); + } + else + await E.Origin.Tell(statLine); } } public class CViewTopStats : Command { - public CViewTopStats() : base("topstats", "view the top 5 players on this server. syntax !topstats", "!ts", Player.Permission.User, 0, false) { } + public CViewTopStats() : base("topstats", "view the top 5 players on this server. syntax !topstats", "ts", Player.Permission.User, 0, false) { } public override async Task ExecuteAsync(Event E) { - List> pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.topStats(); + List> pStats = Stats.statLists.Find(x => x.Port == E.Owner.getPort()).playerStats.GetTopStats(); StringBuilder msgBlder = new StringBuilder(); await E.Origin.Tell("^5--Top Players--"); @@ -54,6 +61,23 @@ namespace StatsPlugin } } + public class CResetStats : Command + { + public CResetStats() : base("resetstats", "reset your stats to factory-new, !syntax !resetstats", "rs", Player.Permission.User, 0, false) { } + + public override async Task ExecuteAsync(Event E) + { + 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.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"); + } + } + /// /// Each server runs from the same plugin ( for easier reloading and reduced memory usage ). /// So, to have multiple stat tracking, we must store a stat struct for each server @@ -89,7 +113,7 @@ namespace StatsPlugin public float Version { - get { return 1f; } + get { return 1.1f; } } public string Author @@ -117,6 +141,8 @@ 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 (E.Type == Event.GType.Stop) @@ -126,10 +152,10 @@ namespace StatsPlugin if (E.Type == Event.GType.Connect) { - resetCounters(E.Origin.clientID, S.getPort()); + ResetCounters(E.Origin.ClientID, S.getPort()); - PlayerStats checkForTrusted = statLists.Find(x => x.Port == S.getPort()).playerStats.getStats(E.Origin); - if (checkForTrusted.playTime >= 4320 && E.Origin.Level < Player.Permission.Trusted) + PlayerStats checkForTrusted = statLists.Find(x => x.Port == S.getPort()).playerStats.GetStats(E.Origin); + if (checkForTrusted.TotalPlayTime >= 4320 && E.Origin.Level < Player.Permission.Trusted) { E.Origin.setLevel(Player.Permission.Trusted); E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Origin); @@ -146,19 +172,19 @@ namespace StatsPlugin if (P == null) continue; - calculateAndSaveSkill(P, statLists.Find(x =>x.Port == S.getPort())); - resetCounters(P.clientID, S.getPort()); + CalculateAndSaveSkill(P, statLists.Find(x =>x.Port == S.getPort())); + ResetCounters(P.ClientID, S.getPort()); - E.Owner.Logger.WriteInfo("Updated skill for client #" + P.databaseID); + E.Owner.Logger.WriteInfo("Updated skill for client #" + P.DatabaseID); //E.Owner.Log.Write(String.Format("\r\nJoin: {0}\r\nInactive Minutes: {1}\r\nnewPlayTime: {2}\r\nnewSPM: {3}\r\nkdrWeight: {4}\r\nMultiplier: {5}\r\nscoreWeight: {6}\r\nnewSkillFactor: {7}\r\nprojectedNewSkill: {8}\r\nKills: {9}\r\nDeaths: {10}", connectionTime[P.clientID].ToShortTimeString(), inactiveMinutes[P.clientID], newPlayTime, newSPM, kdrWeight, Multiplier, scoreWeight, newSkillFactor, disconnectStats.Skill, disconnectStats.Kills, disconnectStats.Deaths)); } } if (E.Type == Event.GType.Disconnect) { - calculateAndSaveSkill(E.Origin, statLists.Find(x=>x.Port == S.getPort())); - resetCounters(E.Origin.clientID, S.getPort()); - E.Owner.Logger.WriteInfo("Updated skill for disconnecting client #" + E.Origin.databaseID); + CalculateAndSaveSkill(E.Origin, statLists.Find(x=>x.Port == S.getPort())); + ResetCounters(E.Origin.ClientID, S.getPort()); + E.Owner.Logger.WriteInfo("Updated skill for disconnecting client #" + E.Origin.DatabaseID); } if (E.Type == Event.GType.Kill) @@ -168,14 +194,14 @@ namespace StatsPlugin Player Killer = E.Origin; StatTracking curServer = statLists.Find(x => x.Port == S.getPort()); - PlayerStats killerStats = curServer.playerStats.getStats(Killer); + PlayerStats killerStats = curServer.playerStats.GetStats(Killer); - curServer.lastKill[E.Origin.clientID] = DateTime.Now; - curServer.Kills[E.Origin.clientID]++; + 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 ((curServer.lastKill[E.Origin.ClientID] - DateTime.Now).TotalSeconds > 60) + curServer.inactiveMinutes[E.Origin.ClientID]++; killerStats.Kills++; @@ -184,12 +210,12 @@ namespace StatsPlugin else killerStats.KDR = Math.Round((double)killerStats.Kills / (double)killerStats.Deaths, 2); - curServer.playerStats.updateStats(Killer, killerStats); + curServer.playerStats.UpdateStats(Killer, killerStats); - curServer.killStreaks[Killer.clientID] += 1; - curServer.deathStreaks[Killer.clientID] = 0; + curServer.killStreaks[Killer.ClientID] += 1; + curServer.deathStreaks[Killer.ClientID] = 0; - await Killer.Tell(messageOnStreak(curServer.killStreaks[Killer.clientID], curServer.deathStreaks[Killer.clientID])); + await Killer.Tell(MessageOnStreak(curServer.killStreaks[Killer.ClientID], curServer.deathStreaks[Killer.ClientID])); } if (E.Type == Event.GType.Death) @@ -199,61 +225,63 @@ namespace StatsPlugin Player Victim = E.Origin; StatTracking curServer = statLists.Find(x => x.Port == S.getPort()); - PlayerStats victimStats = curServer.playerStats.getStats(Victim); + PlayerStats victimStats = curServer.playerStats.GetStats(Victim); victimStats.Deaths++; victimStats.KDR = Math.Round((double)victimStats.Kills / (double)victimStats.Deaths, 2); - curServer.playerStats.updateStats(Victim, victimStats); + curServer.playerStats.UpdateStats(Victim, victimStats); - curServer.deathStreaks[Victim.clientID] += 1; - curServer.killStreaks[Victim.clientID] = 0; + curServer.deathStreaks[Victim.ClientID] += 1; + curServer.killStreaks[Victim.ClientID] = 0; - await Victim.Tell(messageOnStreak(curServer.killStreaks[Victim.clientID], curServer.deathStreaks[Victim.clientID])); + await Victim.Tell(MessageOnStreak(curServer.killStreaks[Victim.ClientID], curServer.deathStreaks[Victim.ClientID])); } } - private void calculateAndSaveSkill(Player P, StatTracking curServer) + private void CalculateAndSaveSkill(Player P, StatTracking curServer) { if (P == null) return; - PlayerStats disconnectStats = curServer.playerStats.getStats(P); - if (curServer.Kills[P.clientID] == 0) + PlayerStats DisconnectingPlayerStats = curServer.playerStats.GetStats(P); + if (curServer.Kills[P.ClientID] == 0) return; - else if (curServer.lastKill[P.clientID] > curServer.connectionTime[P.clientID]) - curServer.inactiveMinutes[P.clientID] += (int)(DateTime.Now - curServer.lastKill[P.clientID]).TotalMinutes; + else if (curServer.lastKill[P.ClientID] > curServer.connectionTime[P.ClientID]) + curServer.inactiveMinutes[P.ClientID] += (int)(DateTime.Now - curServer.lastKill[P.ClientID]).TotalMinutes; - int newPlayTime = (int)(DateTime.Now - curServer.connectionTime[P.clientID]).TotalMinutes - curServer.inactiveMinutes[P.clientID]; + int newPlayTime = (int)(DateTime.Now - curServer.connectionTime[P.ClientID]).TotalMinutes - curServer.inactiveMinutes[P.ClientID]; if (newPlayTime < 2) return; - double newSPM = curServer.Kills[P.clientID] * 50 / Math.Max(1, newPlayTime); - double kdrWeight = Math.Round(Math.Pow(disconnectStats.KDR, 2 / Math.E), 3); - double Multiplier; + // calculate the players Score Per Minute for the current session + double SessionSPM = curServer.Kills[P.ClientID] * 100 / Math.Max(1, newPlayTime); + // calculate how much the KDR should way + // 0.81829 is a Eddie-Generated number that weights the KDR nicely + double KDRWeight = Math.Round(Math.Pow(DisconnectingPlayerStats.KDR, 1.637 / Math.E), 3); + double SPMWeightAgainstAverage; - if (disconnectStats.scorePerMinute == 1) - Multiplier = 1; - else - Multiplier = newSPM / disconnectStats.scorePerMinute; + // if no SPM, weight is 1 else the weight is the current sessions spm / lifetime average score per minute + SPMWeightAgainstAverage = (DisconnectingPlayerStats.scorePerMinute == 1) ? 1 : SessionSPM / DisconnectingPlayerStats.scorePerMinute; - double scoreWeight = (newSPM * (newPlayTime / disconnectStats.playTime)); - double newSkillFactor = Multiplier * scoreWeight; + // calculate the weight of the new play time againmst lifetime playtime + // + double SPMAgainstPlayWeight = newPlayTime / Math.Min(600, DisconnectingPlayerStats.TotalPlayTime); + // calculate the new weight against average times the weight against play time + double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight; - if (Multiplier >= 1) - disconnectStats.scorePerMinute += newSkillFactor; - else - disconnectStats.scorePerMinute -= (scoreWeight - newSkillFactor); + // if the weight is greater than 1, add, else subtract + DisconnectingPlayerStats.scorePerMinute += (SPMWeightAgainstAverage >= 1) ? newSkillFactor : -newSkillFactor; - disconnectStats.Skill = disconnectStats.scorePerMinute * kdrWeight / 10; - disconnectStats.playTime += newPlayTime; + DisconnectingPlayerStats.Skill = DisconnectingPlayerStats.scorePerMinute * KDRWeight / 10; + DisconnectingPlayerStats.TotalPlayTime += newPlayTime; - curServer.playerStats.updateStats(P, disconnectStats); + curServer.playerStats.UpdateStats(P, DisconnectingPlayerStats); } - private void resetCounters(int cID, int serverPort) + private void ResetCounters(int cID, int serverPort) { StatTracking selectedPlayers = statLists.Find(x => x.Port == serverPort); @@ -264,7 +292,7 @@ namespace StatsPlugin selectedPlayers.killStreaks[cID] = 0; } - private String messageOnStreak(int killStreak, int deathStreak) + private String MessageOnStreak(int killStreak, int deathStreak) { String Message = ""; switch (killStreak) @@ -304,24 +332,24 @@ namespace StatsPlugin } } - public void addPlayer(Player P) + public void AddPlayer(Player P) { - Dictionary newPlayer = new Dictionary(); - - newPlayer.Add("npID", P.npID); - newPlayer.Add("KILLS", 0); - newPlayer.Add("DEATHS", 0); - newPlayer.Add("KDR", 0.0); - newPlayer.Add("SKILL", 1.0); - newPlayer.Add("SPM", 1.0); - newPlayer.Add("PLAYTIME", 1.0); - + Dictionary newPlayer = new Dictionary + { + { "npID", P.NetworkID }, + { "KILLS", 0 }, + { "DEATHS", 0 }, + { "KDR", 0.0 }, + { "SKILL", 1.0 }, + { "SPM", 1.0 }, + { "PLAYTIME", 1.0 } + }; Insert("STATS", newPlayer); } - public PlayerStats getStats(Player P) + public PlayerStats GetStats(Player P) { - DataTable Result = GetDataTable("STATS", new KeyValuePair("npID", P.npID)); + DataTable Result = GetDataTable("STATS", new KeyValuePair("npID", P.NetworkID)); if (Result != null && Result.Rows.Count > 0) { @@ -338,26 +366,38 @@ namespace StatsPlugin else { - addPlayer(P); - return getStats(P); + AddPlayer(P); + return GetStats(P); } } - public void updateStats(Player P, PlayerStats S) + public int GetTotalKills() { - Dictionary updatedPlayer = new Dictionary(); - - updatedPlayer.Add("KILLS", S.Kills); - updatedPlayer.Add("DEATHS", S.Deaths); - updatedPlayer.Add("KDR", Math.Round(S.KDR, 2)); - updatedPlayer.Add("SKILL", Math.Round(S.Skill, 1)); - updatedPlayer.Add("SPM", Math.Round(S.scorePerMinute, 1)); - updatedPlayer.Add("PLAYTIME", S.playTime); - - Update("STATS", updatedPlayer, new KeyValuePair("npID", P.npID)); + var Result = GetDataTable("SELECT SUM(KILLS) FROM STATS"); + return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt32(Result.Rows[0][0]); } - public List> topStats() + public int GetTotalPlaytime() + { + var Result = GetDataTable("SELECT SUM(PLAYTIME) FROM STATS"); + return Result.Rows[0][0].GetType() == typeof(DBNull) ? 0 : Convert.ToInt32(Result.Rows[0][0]) / 60; + } + + public void UpdateStats(Player P, PlayerStats S) + { + Dictionary updatedPlayer = new Dictionary + { + { "KILLS", S.Kills }, + { "DEATHS", S.Deaths }, + { "KDR", Math.Round(S.KDR, 2) }, + { "SKILL", Math.Round(S.Skill, 1) }, + { "SPM", Math.Round(S.scorePerMinute, 1) }, + { "PLAYTIME", S.TotalPlayTime } + }; + Update("STATS", updatedPlayer, new KeyValuePair("npID", P.NetworkID)); + } + + public List> GetTopStats() { String Query = String.Format("SELECT * FROM STATS WHERE SKILL > 0 AND KDR < '{0}' AND KILLS > '{1}' AND PLAYTIME > '{2}' ORDER BY SKILL DESC LIMIT '{3}'", 10, 150, 60, 5); DataTable Result = GetDataTable(Query); @@ -392,7 +432,7 @@ namespace StatsPlugin KDR = DR; Skill = S; scorePerMinute = sc; - playTime = P; + TotalPlayTime = P; } public int Kills; @@ -400,6 +440,6 @@ namespace StatsPlugin public double KDR; public double Skill; public double scorePerMinute; - public int playTime; + public int TotalPlayTime; } } \ No newline at end of file diff --git a/Votemap Plugin/Plugin.cs b/Votemap Plugin/Plugin.cs index 92154705..25f06261 100644 --- a/Votemap Plugin/Plugin.cs +++ b/Votemap Plugin/Plugin.cs @@ -31,7 +31,7 @@ namespace Votemap_Plugin // we only want to allow a vote during a vote session if (voting.voteInSession) { - if (voting.hasVoted(E.Origin.npID)) + if (voting.hasVoted(E.Origin.NetworkID)) await E.Origin.Tell("You have already voted. Use ^5!vc ^7to ^5cancel ^7your vote"); else { @@ -42,7 +42,7 @@ namespace Votemap_Plugin await E.Origin.Tell("^1" + E.Data + " is not a recognized map"); else { - voting.castVote(E.Origin.npID, votedMap); + voting.castVote(E.Origin.NetworkID, votedMap); await E.Origin.Tell("You voted for ^5" + votedMap.Alias); } } @@ -63,9 +63,9 @@ namespace Votemap_Plugin if (voting.voteInSession) { - if (voting.hasVoted(E.Origin.npID)) + if (voting.hasVoted(E.Origin.NetworkID)) { - voting.cancelVote(E.Origin.npID); + voting.cancelVote(E.Origin.NetworkID); await E.Origin.Tell("Vote cancelled"); }