From cd85a5c38418e1672a667deefb56ce74fb7b5309 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Thu, 20 Aug 2015 00:06:44 -0500 Subject: [PATCH] Massive refactoring and rudimentary plugin support. --- Admin/Command.cs | 188 +++---- Admin/Database.cs | 33 +- Admin/File.cs | 68 +-- Admin/Heartbeat.cs | 1 + Admin/IW4M ADMIN.csproj | 43 +- Admin/IW4MAdmin.exe.config | 11 - Admin/IW4_GameStructs.cs | 14 - Admin/Log.cs | 4 +- Admin/Main.cs | 51 +- Admin/Manager.cs | 24 +- Admin/Plugins.cs | 64 +++ Admin/Properties/Settings.Designer.cs | 2 +- Admin/Server.cs | 701 ++++-------------------- Admin/TrueSkill.cs | 7 +- Admin/Utilities.cs | 40 +- Admin/WebFront.cs | 153 +++--- Admin/app.config | 12 +- Admin/app.manifest | 54 ++ Admin/lib/SharedLibary.dll | Bin 0 -> 41472 bytes Admin/plugins/SamplePlugin.dll | Bin 0 -> 5632 bytes IW4M Admin.sln | 14 +- SamplePlugin/Main.cs | 45 ++ SamplePlugin/Properties/AssemblyInfo.cs | 36 ++ SamplePlugin/SamplePlugin.csproj | 57 ++ SharedLibary/Ban.cs | 30 + SharedLibary/Command.cs | 30 + SharedLibary/Database.cs | 630 +++++++++++++++++++++ SharedLibary/Dvar.cs | 19 + {Admin => SharedLibary}/Event.cs | 23 +- SharedLibary/File.cs | 134 +++++ SharedLibary/Log.cs | 61 +++ SharedLibary/Map.cs | 19 + SharedLibary/Player.cs | 235 ++++++++ SharedLibary/Properties/AssemblyInfo.cs | 36 ++ SharedLibary/Report.cs | 21 + SharedLibary/Server.cs | 403 ++++++++++++++ SharedLibary/SharedLibrary.csproj | 72 +++ SharedLibary/SharedLibrary.sln | 22 + SharedLibary/Utilities.cs | 243 ++++++++ 39 files changed, 2601 insertions(+), 999 deletions(-) delete mode 100644 Admin/IW4MAdmin.exe.config create mode 100644 Admin/Plugins.cs create mode 100644 Admin/app.manifest create mode 100644 Admin/lib/SharedLibary.dll create mode 100644 Admin/plugins/SamplePlugin.dll create mode 100644 SamplePlugin/Main.cs create mode 100644 SamplePlugin/Properties/AssemblyInfo.cs create mode 100644 SamplePlugin/SamplePlugin.csproj create mode 100644 SharedLibary/Ban.cs create mode 100644 SharedLibary/Command.cs create mode 100644 SharedLibary/Database.cs create mode 100644 SharedLibary/Dvar.cs rename {Admin => SharedLibary}/Event.cs (84%) create mode 100644 SharedLibary/File.cs create mode 100644 SharedLibary/Log.cs create mode 100644 SharedLibary/Map.cs create mode 100644 SharedLibary/Player.cs create mode 100644 SharedLibary/Properties/AssemblyInfo.cs create mode 100644 SharedLibary/Report.cs create mode 100644 SharedLibary/Server.cs create mode 100644 SharedLibary/SharedLibrary.csproj create mode 100644 SharedLibary/SharedLibrary.sln create mode 100644 SharedLibary/Utilities.cs diff --git a/Admin/Command.cs b/Admin/Command.cs index fb82f8d2..815d4e83 100644 --- a/Admin/Command.cs +++ b/Admin/Command.cs @@ -1,64 +1,10 @@ using System; using System.Collections.Generic; using System.Text; +using SharedLibrary; namespace IW4MAdmin { - abstract class Command - { - public Command(String N, String D, String U, Player.Permission P, int args, bool nT) - { - Name = N; - Description = D; - Usage = U; - Permission = P; - Arguments = args; - hasTarget = nT; - } - - //Get command name - public String getName() - { - return Name; - } - //Get description on command - public String getDescription() - { - return Description; - } - //Get the example usage of the command - public String getAlias() - { - return Usage; - } - //Get the required permission to execute the command - public Player.Permission getNeededPerm() - { - return Permission; - } - - public int getNumArgs() - { - return Arguments; - } - - public bool needsTarget() - { - return hasTarget; - } - - //Execute the command - abstract public void Execute(Event E); - - private String Name; - private String Description; - private String Usage; - private int Arguments; - private bool hasTarget; - - public Player.Permission Permission; - } - class Owner : Command { public Owner(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } @@ -83,13 +29,13 @@ namespace IW4MAdmin public override void Execute(Event E) { - if (E.Origin.getLevel() <= E.Target.getLevel()) - E.Origin.Tell("You cannot warn " + E.Target.getName()); + if (E.Origin.Level <= E.Target.Level) + E.Origin.Tell("You cannot warn " + E.Target.Name); else { - E.Target.LastOffense = Utilities.removeWords(E.Data, 1); + E.Target.lastOffense = Utilities.removeWords(E.Data, 1); E.Target.Warnings++; - String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", E.Target.Warnings, E.Target.getName(), E.Target.LastOffense); + String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", E.Target.Warnings, E.Target.Name, E.Target.lastOffense); E.Owner.Broadcast(Message); if (E.Target.Warnings >= 4) E.Target.Kick("You were kicked for too many warnings!"); @@ -103,9 +49,9 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Target.LastOffense = String.Empty; + E.Target.lastOffense = String.Empty; E.Target.Warnings = 0; - String Message = String.Format("All warning cleared for {0}", E.Target.getName()); + String Message = String.Format("All warning cleared for {0}", E.Target.Name); E.Owner.Broadcast(Message); } } @@ -116,12 +62,12 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Target.LastOffense = Utilities.removeWords(E.Data, 1); - String Message = "^1Player Kicked: ^5" + E.Target.LastOffense + " ^1Admin: ^5" + E.Origin.getName(); - if (E.Origin.getLevel() > E.Target.getLevel()) + E.Target.lastOffense = Utilities.removeWords(E.Data, 1); + String Message = "^1Player Kicked: ^5" + E.Target.lastOffense + " ^1Admin: ^5" + E.Origin.Name; + if (E.Origin.Level > E.Target.Level) E.Target.Kick(Message); else - E.Origin.Tell("You cannot kick " + E.Target.getName()); + E.Origin.Tell("You cannot kick " + E.Target.Name); } } @@ -131,7 +77,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Owner.Broadcast("^1" + E.Origin.getName() + " - ^6" + E.Data + "^7"); + E.Owner.Broadcast("^1" + E.Origin.Name + " - ^6" + E.Data + "^7"); } } @@ -141,12 +87,12 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Target.LastOffense = Utilities.removeWords(E.Data, 1); - String Message = "^1Player Temporarily Banned: ^5" + E.Target.LastOffense + "^7 (1 hour)"; - if (E.Origin.getLevel() > E.Target.getLevel()) + E.Target.lastOffense = Utilities.removeWords(E.Data, 1); + String Message = "^1Player Temporarily Banned: ^5" + E.Target.lastOffense + "^7 (1 hour)"; + if (E.Origin.Level > E.Target.Level) E.Target.tempBan(Message); else - E.Origin.Tell("You cannot temp ban " + E.Target.getName()); + E.Origin.Tell("You cannot temp ban " + E.Target.Name); } } @@ -156,20 +102,20 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Target.LastOffense = Utilities.removeWords(E.Data, 1); + E.Target.lastOffense = Utilities.removeWords(E.Data, 1); E.Target.lastEvent = E; // needs to be fixed String Message; if (E.Owner.Website == null) - Message = "^1Player Banned: ^5" + E.Target.LastOffense; + Message = "^1Player Banned: ^5" + E.Target.lastOffense; else - Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal " + E.Owner.Website; - if (E.Origin.getLevel() > E.Target.getLevel()) + Message = "^1Player Banned: ^5" + E.Target.lastOffense + "^7 (appeal " + E.Owner.Website; + if (E.Origin.Level > E.Target.Level) { E.Target.Ban(Message, E.Origin); - E.Origin.Tell(String.Format("Sucessfully banned ^5{0} ^7({1})", E.Target.getName(), E.Target.getID())); + E.Origin.Tell(String.Format("Sucessfully banned ^5{0} ^7({1})", E.Target.Name, E.Target.npID)); } else - E.Origin.Tell("You cannot ban " + E.Target.getName()); + E.Origin.Tell("You cannot ban " + E.Target.Name); } } @@ -180,7 +126,7 @@ namespace IW4MAdmin public override void Execute(Event E) { if (E.Owner.Unban(E.Data.Trim(), E.Target)) - E.Origin.Tell("Successfully unbanned " + E.Target.getName()); + E.Origin.Tell("Successfully unbanned " + E.Target.Name); else E.Origin.Tell("Unable to find a ban for that GUID"); } @@ -192,7 +138,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.getName(), E.Origin.getClientNum(), E.Origin.getID(), E.Origin.getDBID(), Utilities.levelToColor(E.Origin.getLevel()), E.Origin.getIP()); + 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, Utilities.levelToColor(E.Origin.Level), E.Origin.IP); E.Origin.Tell(You); } } @@ -210,7 +156,7 @@ namespace IW4MAdmin if (P == null) continue; - E.Origin.Tell(String.Format("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(P.getLevel()), P.getClientNum(), P.getName(), Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.getLevel().ToString().Length))); + E.Origin.Tell(String.Format("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(P.Level), P.clientID, P.Name, Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length))); } } } @@ -229,9 +175,9 @@ namespace IW4MAdmin bool found = false; foreach (Command C in E.Owner.getCommands()) { - if (C.getName().Contains(cmd) || C.getName() == cmd) + if (C.Name.Contains(cmd) || C.Name == cmd) { - E.Origin.Tell(" [^3" + C.getName() + "^7] " + C.getDescription()); + E.Origin.Tell(" [^3" + C.Name + "^7] " + C.Description); found = true; } } @@ -247,9 +193,9 @@ namespace IW4MAdmin foreach (Command C in E.Owner.getCommands()) { - if (E.Origin.getLevel() >= C.getNeededPerm()) + if (E.Origin.Level >= C.Permission) { - _commands = _commands + " [^3" + C.getName() + "^7] "; + _commands = _commands + " [^3" + C.Name + "^7] "; if (count >= 4) { E.Origin.Tell(_commands); @@ -305,7 +251,7 @@ namespace IW4MAdmin { E.Target.setLevel(newPerm); E.Target.Tell("Congratulations! You have been promoted to ^3" + newPerm); - E.Origin.Tell(E.Target.getName() + " was successfully promoted!"); + E.Origin.Tell(E.Target.Name + " was successfully promoted!"); //NEEED TO MOVE E.Owner.clientDB.updatePlayer(E.Target); } @@ -347,26 +293,15 @@ namespace IW4MAdmin { foreach (Player P in E.Owner.getPlayers()) { - if (P != null && P.getLevel() > Player.Permission.Flagged && !P.Masked) + if (P != null && P.Level > Player.Permission.Flagged && !P.Masked) { - E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.getLevel()), P.getName())); + E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); } } } } } - class Wisdom : Command - { - public Wisdom(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } - - public override void Execute(Event E) - { - E.Owner.Broadcast(E.Owner.Wisdom()); - } - } - - class MapCMD : Command { public MapCMD(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } @@ -407,7 +342,7 @@ namespace IW4MAdmin foreach (Player P in db_players) { - String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.getName(), P.getDBID(), Utilities.levelToColor(P.getLevel()), P.getIP(), P.getLastConnection()); + String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.Name, P.databaseID, Utilities.levelToColor(P.Level), P.IP, P.getLastConnection()); E.Origin.Tell(mesg); } } @@ -453,7 +388,7 @@ namespace IW4MAdmin if (Current != null) { - String mesg = String.Format("^1{0} ^7now goes by ^5{1}^7 [^3{2}^7]", lookingFor, Current.getName(), Current.getDBID()); + String mesg = String.Format("^1{0} ^7now goes by ^5{1}^7 [^3{2}^7]", lookingFor, Current.Name, Current.databaseID); E.Origin.Tell(mesg); } } @@ -484,8 +419,8 @@ namespace IW4MAdmin { E.Data = Utilities.removeWords(E.Data, 1); E.Target.Alert(); - E.Target.Tell("^1" + E.Origin.getName() + " ^3[PM]^7 - " + E.Data); - E.Origin.Tell(String.Format("To ^3{0} ^7-> {1}", E.Target.getName(), E.Data)); + E.Target.Tell("^1" + E.Origin.Name + " ^3[PM]^7 - " + E.Data); + E.Origin.Tell(String.Format("To ^3{0} ^7-> {1}", E.Target.Name, E.Data)); } } @@ -505,11 +440,11 @@ namespace IW4MAdmin else { - E.Target.stats = E.Owner.statDB.getStats(E.Target.getDBID()); + E.Target.stats = E.Owner.statDB.getStats(E.Target.databaseID); if (E.Target.stats == null) E.Origin.Tell("That person does not have any stats at this time!"); else - E.Origin.Tell(String.Format("[^3{4}^7] ^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Target.stats.Kills, E.Target.stats.Deaths, E.Target.stats.KDR, E.Target.stats.Skill, E.Target.getName())); + E.Origin.Tell(String.Format("[^3{4}^7] ^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", E.Target.stats.Kills, E.Target.stats.Deaths, E.Target.stats.KDR, E.Target.stats.Skill, E.Target.Name)); } } } @@ -526,7 +461,7 @@ namespace IW4MAdmin foreach (Stats S in Top) { Player P = E.Owner.clientDB.getPlayer(S.statIndex); - if (P != null && P.getLevel() != Player.Permission.Banned) + if (P != null && P.Level != Player.Permission.Banned) { P.stats = S; TopP.Add(P); @@ -539,7 +474,7 @@ namespace IW4MAdmin foreach (Player P in TopP) { if (P != null) - E.Origin.Tell(String.Format("^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL", P.getName(), P.stats.KDR, P.stats.Skill)); + E.Origin.Tell(String.Format("^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL", P.Name, P.stats.KDR, P.stats.Skill)); } } @@ -567,7 +502,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Owner.RCON.addRCON(String.Format("admin_lastevent {0};{1}", "balance", E.Origin.getID())); //Let gsc do the magic + E.Origin.currentServer.executeCommand(String.Format("admin_lastevent {0};{1}", "balance", E.Origin.npID)); //Let gsc do the magic } } @@ -577,7 +512,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Owner.RCON.addRCON(String.Format("admin_lastevent {0};{1};{2};{3}", "goto", E.Origin.getID(), E.Target.getName(), E.Data)); //Let gsc do the magic + E.Origin.currentServer.executeCommand(String.Format("admin_lastevent {0};{1};{2};{3}", "goto", E.Origin.npID, E.Target.Name, E.Data)); //Let gsc do the magic } } @@ -587,22 +522,22 @@ namespace IW4MAdmin public override void Execute(Event E) { - if (E.Target.getLevel() >= E.Origin.getLevel()) + if (E.Target.Level >= E.Origin.Level) { - E.Origin.Tell("You cannot flag " + E.Target.getName()); + E.Origin.Tell("You cannot flag " + E.Target.Name); return; } - if (E.Target.getLevel() == Player.Permission.Flagged) + if (E.Target.Level == Player.Permission.Flagged) { E.Target.setLevel(Player.Permission.User); - E.Origin.Tell("You have ^5unflagged ^7" + E.Target.getName()); + E.Origin.Tell("You have ^5unflagged ^7" + E.Target.Name); } else { E.Target.setLevel(Player.Permission.Flagged); - E.Origin.Tell("You have ^5flagged ^7" + E.Target.getName()); + E.Origin.Tell("You have ^5flagged ^7" + E.Target.Name); } E.Owner.clientDB.updatePlayer(E.Target); @@ -621,17 +556,17 @@ namespace IW4MAdmin return; } - if (E.Target.getLevel() > E.Origin.getLevel()) + if (E.Target.Level > E.Origin.Level) { - E.Origin.Tell("You cannot report " + E.Target.getName()); + E.Origin.Tell("You cannot report " + E.Target.Name); return; } E.Data = Utilities.removeWords(E.Data, 1); E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data)); - E.Origin.Tell("Successfully reported " + E.Target.getName()); + E.Origin.Tell("Successfully reported " + E.Target.Name); - E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.getName(), E.Target.getName(), E.Data)); + E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data)); } } @@ -653,7 +588,7 @@ namespace IW4MAdmin if (count > 8) i = count - 8; Report R = E.Owner.Reports[i]; - E.Origin.Tell(String.Format("^5{0}^7->^1{1}^7: {2}", R.Origin.getName(), R.Target.getName(), R.Reason)); + E.Origin.Tell(String.Format("^5{0}^7->^1{1}^7: {2}", R.Origin.Name, R.Target.Name, R.Reason)); } } } @@ -665,7 +600,7 @@ namespace IW4MAdmin public override void Execute(Event E) { E.Data = Utilities.removeWords(E.Data, 1); - E.Owner.RCON.addRCON(String.Format("admin_lastevent tell;{0};{1};{2}", E.Origin.getID(), E.Target.getID(), E.Data)); + E.Origin.currentServer.executeCommand(String.Format("admin_lastevent tell;{0};{1};{2}", E.Origin.npID, E.Target.npID, E.Data)); } } @@ -700,7 +635,7 @@ namespace IW4MAdmin return; } - Ban B = E.Owner.Bans.Find(b => b.getID().Equals(E.Target.getID())); + Ban B = E.Owner.Bans.Find(b => b.npID.Equals(E.Target.npID)); if (B == null) { @@ -708,7 +643,7 @@ namespace IW4MAdmin return; } - Player Banner = E.Owner.clientDB.getPlayer(B.getBanner(), -1); + Player Banner = E.Owner.clientDB.getPlayer(B.bannedByID, -1); if (Banner == null) { @@ -716,7 +651,7 @@ namespace IW4MAdmin return; } - E.Origin.Tell(String.Format("^1{0} ^7was banned by ^5{1} ^7for: {2}", E.Target.getName(), Banner.getName(), B.getReason())); + E.Origin.Tell(String.Format("^1{0} ^7was banned by ^5{1} ^7for: {2}", E.Target.Name, Banner.Name, B.Reason)); } } @@ -726,7 +661,7 @@ namespace IW4MAdmin public override void Execute(Event E) { - E.Target.Alias = E.Owner.aliasDB.getPlayer(E.Target.getDBID()); + E.Target.Alias = E.Owner.aliasDB.getPlayer(E.Target.databaseID); if (E.Target.Alias == null) { @@ -734,7 +669,7 @@ namespace IW4MAdmin return; } - E.Target.Tell("[^3" + E.Target.getName() + "^7]"); + E.Target.Tell("[^3" + E.Target.Name + "^7]"); StringBuilder message = new StringBuilder(); List playerAliases = new List(); @@ -746,7 +681,7 @@ namespace IW4MAdmin { foreach (String S in P.Alias.getNames()) { - if (S != String.Empty && S != E.Target.getName()) + if (S != String.Empty && S != E.Target.Name) message.Append(S + " | "); } } @@ -778,9 +713,8 @@ namespace IW4MAdmin public override void Execute(Event E) { - String[] Response = E.Owner.RCON.addRCON(E.Data.Trim()); - if (Response != null && Response.Length > 0) - E.Origin.Tell("Successfuly sent RCON command!"); + E.Origin.currentServer.executeCommand(E.Data.Trim()); + E.Origin.Tell("Successfuly sent RCON command!"); } } } diff --git a/Admin/Database.cs b/Admin/Database.cs index 8ffa2891..2314636e 100644 --- a/Admin/Database.cs +++ b/Admin/Database.cs @@ -6,10 +6,11 @@ using System.Data; using System.Linq; using System.IO; using System.Collections; +using SharedLibrary; namespace IW4MAdmin { - abstract class Database + abstract class DatabaseA : SharedLibrary.Database { public Database(String FN) { @@ -336,12 +337,12 @@ namespace IW4MAdmin { Dictionary newPlayer = new Dictionary(); - newPlayer.Add("Name", Utilities.removeNastyChars(P.getName())); - newPlayer.Add("npID", P.getID()); - newPlayer.Add("Level", (int)P.getLevel()); + newPlayer.Add("Name", Utilities.removeNastyChars(P.Name)); + newPlayer.Add("npID", P.npID); + newPlayer.Add("Level", (int)P.Level); newPlayer.Add("LastOffense", ""); newPlayer.Add("Connections", 1); - newPlayer.Add("IP", P.getIP()); + newPlayer.Add("IP", P.IP); newPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); Insert("CLIENTS", newPlayer); @@ -352,15 +353,15 @@ namespace IW4MAdmin { Dictionary updatedPlayer = new Dictionary(); - updatedPlayer.Add("Name", P.getName()); - updatedPlayer.Add("npID", P.getID()); - updatedPlayer.Add("Level", (int)P.getLevel()); - updatedPlayer.Add("LastOffense", P.getLastO()); - updatedPlayer.Add("Connections", P.getConnections()); - updatedPlayer.Add("IP", P.getIP()); + updatedPlayer.Add("Name", P.Name); + updatedPlayer.Add("npID", P.npID); + updatedPlayer.Add("Level", (int)P.Level); + updatedPlayer.Add("LastOffense", P.LastOffense); + updatedPlayer.Add("Connections", P.Connections); + updatedPlayer.Add("IP", P.IP); updatedPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); - Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.getID())); + Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.npID)); } @@ -433,7 +434,7 @@ namespace IW4MAdmin { Dictionary newPlayer = new Dictionary(); - newPlayer.Add("Number", P.getDBID()); + newPlayer.Add("Number", P.databaseID); newPlayer.Add("KILLS", 0); newPlayer.Add("DEATHS", 0); newPlayer.Add("KDR", 0); @@ -456,10 +457,10 @@ namespace IW4MAdmin updatedPlayer.Add("DEATHS", P.stats.Deaths); updatedPlayer.Add("KDR", Math.Round(P.stats.KDR, 2)); updatedPlayer.Add("SKILL", P.stats.Skill); - updatedPlayer.Add("MEAN", P.stats.Rating.Mean); - updatedPlayer.Add("DEV", P.stats.Rating.StandardDeviation); + //updatedPlayer.Add("MEAN", P.stats.Rating.Mean); + //updatedPlayer.Add("DEV", P.stats.Rating.StandardDeviation); - Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.getDBID())); + Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.databaseID)); } //Returns top 5 players (we filter through them later) diff --git a/Admin/File.cs b/Admin/File.cs index 4841cc52..c6008609 100644 --- a/Admin/File.cs +++ b/Admin/File.cs @@ -5,9 +5,9 @@ using System.IO; namespace IW4MAdmin { - class file + class IFile { - public file(String fileName) + public IFile(String fileName) { //Not safe for directories with more than one folder but meh _Directory = fileName.Split('\\')[0]; @@ -42,11 +42,10 @@ namespace IW4MAdmin } } - public file(String file, bool write) + public IFile(String file, bool write) { Name = file; writeHandle = new StreamWriter(new FileStream(Name, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)); - // writeHandle.AutoFlush = true; sze = 0; } @@ -80,11 +79,6 @@ namespace IW4MAdmin return null; } - public int getNumLines() - { - return 0; - } - public void Close() { if(Handle != null) @@ -93,46 +87,6 @@ namespace IW4MAdmin writeHandle.Close(); } - //FROM http://stackoverflow.com/questions/398378/get-last-10-lines-of-very-large-text-file-10gb-c-sharp - public string ReadEndTokens() - { - Encoding encoding = Encoding.ASCII; - string tokenSeparator = "\n"; - int numberOfTokens = 2; - - int sizeOfChar = encoding.GetByteCount("\n"); - byte[] buffer = encoding.GetBytes(tokenSeparator); - - using (FileStream fs = new FileStream(this.Name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - Int64 tokenCount = 0; - Int64 endPosition = fs.Length / sizeOfChar; - - for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar) - { - fs.Seek(-position, SeekOrigin.End); - fs.Read(buffer, 0, buffer.Length); - - if (encoding.GetString(buffer) == tokenSeparator) - { - tokenCount++; - if (tokenCount == numberOfTokens) - { - byte[] returnBuffer = new byte[fs.Length - fs.Position]; - fs.Read(returnBuffer, 0, returnBuffer.Length); - return encoding.GetString(returnBuffer); - } - } - } - - // handle case where number of tokens in file is less than numberOfTokens - fs.Seek(0, SeekOrigin.Begin); - buffer = new byte[fs.Length]; - fs.Read(buffer, 0, buffer.Length); - return encoding.GetString(buffer); - } - } - public String[] readAll() { return Handle.ReadToEnd().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); @@ -143,22 +97,6 @@ namespace IW4MAdmin return Handle.ReadToEnd(); } - public String[] end(int neededLines) - { - var lines = new List(); - while (!Handle.EndOfStream) - { - String lins = Handle.ReadLine(); - lines.Add(lins.ToString()); - if (lines.Count > neededLines) - { - lines.RemoveAt(0); - } - } - - return lines.ToArray(); - } - public String[] Tail(int lineCount) { var buffer = new List(lineCount); diff --git a/Admin/Heartbeat.cs b/Admin/Heartbeat.cs index 3835d813..986ceade 100644 --- a/Admin/Heartbeat.cs +++ b/Admin/Heartbeat.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using SharedLibrary; namespace IW4MAdmin { diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj index fd1bcd77..e0845054 100644 --- a/Admin/IW4M ADMIN.csproj +++ b/Admin/IW4M ADMIN.csproj @@ -71,56 +71,59 @@ IW4MAdmin.ico - IW4MAdmin.Program + + OnOutputUpdated - true + false + + - Properties\app.manifest + app.manifest ..\packages\Kayak.0.7.2\lib\Kayak.dll + False False bin\Debug\Moserware.Skills.dll + False + + + ..\SharedLibary\SharedLibary\bin\Debug\SharedLibary.dll + False + False libs\System.Data.SQLite.dll + False - - - - - - - + True True Settings.settings - - @@ -128,6 +131,7 @@ + PreserveNewest @@ -141,8 +145,12 @@ PreserveNewest - PreserveNewest + Always + + PreserveNewest + + Always @@ -177,9 +185,6 @@ PreserveNewest - - Always - PreserveNewest @@ -298,15 +303,13 @@ cd "$(TargetDir)" -del *.dll del *.config del *.application del *.pdb +del *.dll del *.manifest del *.rm -cd .. -cd .. -copy IW4MAdmin.exe.config $(TargetDir)\IW4MAdmin.exe.config +del *.log + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Admin/lib/SharedLibary.dll b/Admin/lib/SharedLibary.dll new file mode 100644 index 0000000000000000000000000000000000000000..12db12328450fea0c55bd0c470f71675e51df366 GIT binary patch literal 41472 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%0DE9meXHi>pmt`12F*4Dstv1jb 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 literal 0 HcmV?d00001 diff --git a/Admin/plugins/SamplePlugin.dll b/Admin/plugins/SamplePlugin.dll new file mode 100644 index 0000000000000000000000000000000000000000..d991740bd33050385a0267ba5f9641a70581c68d GIT binary patch literal 5632 zcmeHLTWlOx8UAP1UfXMX$=b1R#_LID zXEtYM9h-1T6$lm{r4P{jj0RB9=WP(cFm5UDRf#S29U2_Ynq5EAMG;rq|d z+UrYNcx=_Pp6{Iha{lw5f6h7o8P9z78x$gJ5SDWs3 zzpk9U+nrstJgp?$g3yavUUwYV*K(#N%8q6^T6!*{6PIPFe?EPqssIf-g2>MJ79rw+3A9RY1Lnh}M_zg-Hjp%Y* zcp?u<`Zj_FPgKqabx=m&eO#Ef3q>|Zm+`Qz{dj812+>##DVzH^t|;uAO7%3~O*G#` zq)6`n4=bub*OKUBxC-d(?CgyZMG(LCL_LAUwqv0iZD2-1H`-A(AGm!0?Do1?U8lH) zPHHb)kA&S0U~ebjrC42;_!%S(E-XiSq0YRP#`gNo_HciDtUeb0c5ArFJqST8+;zS^ z91F+lzitiw`8ZtqgaU64Gkh6vplj15_*6%y<=ojPb_PB@fU3FTp>(08v$el7EN-E1 zV}ta^eGn>5UFTbyjz%y<`1ldE7t14Zd@S?Cm=Z*f-^E%go`?@6hLVqQEbGYzzKVC# z^Ci4?thZr2JsDqEPQhc1Wvut_AV58f8TxlaT0Ku)Yndz4w#g=w6%a=O^qA_P;_ zjzur;3fsz2X2bK%BF*Kln0cS#dEXT@v1U3xO{|;wvTu^%&bofu<-A4{fqs0U?D$sE zj4zqOvs?#Tm$JGjnEoWvo_XCBS4Vy9=o}lU3=v;2S8R*{Z5s7FvzW6tvX*a~TZ&b7 z+Vt|mDzWNr;kfIpScS6C?omn6zwjmoOMMZRrKa z^?WPuQQFLv3k7}KP!%3t6P6yl+2JglE5W#^^%e{n;sw*z*JaDwaw&NI+z+ChWm|qt z$meZ+!xS`cilXK5@}M~c*m8*NLoj#U0ai|Y!kW1>i#0=&t|;n0(~``Z*biyl*J(_+ zx{=pCzAI3NPbT)IPbK7$GIqFylbSLf=~R?FleBFzjq>C|R)mH_2KKgw{u^lf;H-n{ zMr#k7^*jd6WN8)BomMoQ3JLlm_}5{@LoJ|n4IWi2VcUS0!#EmUq#I>>Ed_fYx4dsI{ii z@Qxmj<2s21-Eol~4aPqWtHI3hYJT`c^5K`SJT>*rjpv_zSvm0zHNN)w<)wqEcb^Ms zq||GQ($-oBj54T9$ELa27}3H?G#ZUP-Kd7bZHss=phq-Jp=k8bp?XqLMH?F07TYcy zjz$mT*QkcUsB60rjW$jx^gw)eBD;C=JQ8e@PxHk?p=@;jrYLQBB`i)}VEed_wkgq4 zF@;)c4`f_b6kc&%3bk#X5!%mR(X_!t@&r+zLdTNEsnjWB=;T0dW$?s6Dwj_T=y}5! zIQgiN8#EHhl#zmFi$V=a+=1}J4Mqtr9%xi<$45A&XVuPgLNCp_&cu4&lxJUdRk+tZ z>BHu?0kSq70_#oOCEvv5Y9W)({Qhsh?!IHa_T(FXHOje9raL%a=T9%Eas1@m^<^A< ze71Yb)8|q%1EWUKa+Yi7x$NeyEMu3Ox@T?^#7jnw1Ms0O!M&dSKf-N|Tf0m3{=X%; zH13MDZO`a9vt*_;O_`oq6mZ&JdUPrLZ6$KQ_U zM~L3$4H}fU)f8Gw__n?ToS+4?rfH65K~DoG(dKfe?(hGp+#q=bE|vN-6+(W))R>iA z{uWYTRmaIbi5zI-M4v{kSixz}<(TZ1g_N_N2f2=HV99(U73jxx2^dx2lMgMeNPR!2_D%)*(-Le8umCxdaTd3nAzW5Y%Q=iio%CD;(~bj!yi za#UjT;W1;-=UH;T7N~VtoRuS(uy?<);>d?Keq7E_8*H3K|AOp2j);_yBiZu;GCkih zcJnlRWoY;f!k;AJM27|TWiIH)(PLk#@nDLx?f>S}u#DwAY`O5XjNI+l%", "s", Player.Permission.Moderator, 1, false) { } + + public override void Execute(Event E) + { + Server originatingServer = E.Owner; + String Message = E.Data; + String Sender = E.Origin.Name; + + for (int i = 0; i < 10; i++) + originatingServer.Broadcast(String.Format("^7{0}: {1}", Sender, Message)); + } + } + + public class InvalidCommandExample + { + private void doNotDoThis() { } + } +} \ No newline at end of file diff --git a/SamplePlugin/Properties/AssemblyInfo.cs b/SamplePlugin/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0af795a6 --- /dev/null +++ b/SamplePlugin/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SamplePlugin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SamplePlugin")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1d848d36-bf25-4bc0-acdd-67db2d014d45")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SamplePlugin/SamplePlugin.csproj b/SamplePlugin/SamplePlugin.csproj new file mode 100644 index 00000000..2e0c4602 --- /dev/null +++ b/SamplePlugin/SamplePlugin.csproj @@ -0,0 +1,57 @@ + + + + + Debug + AnyCPU + {4785AB75-66F3-4391-985D-63A5A049A0FA} + Library + Properties + SamplePlugin + SamplePlugin + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\SharedLibary\bin\Release\SharedLibary.dll + False + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SharedLibary/Ban.cs b/SharedLibary/Ban.cs new file mode 100644 index 00000000..71def7c4 --- /dev/null +++ b/SharedLibary/Ban.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public class Ban + { + public Ban(String Reas, String TargID, String From, DateTime time, String ip) + { + Reason = Reas; + npID = TargID; + bannedByID = From; + When = time; + IP = ip; + } + + public String getWhen() + { + return When.ToString("MM/dd/yy HH:mm:ss"); ; + } + + public String Reason { get; private set; } + public String npID { get; private set; } + public String bannedByID { get; private set; } + public DateTime When { get; private set; } + public String IP { get; private set; } + } +} diff --git a/SharedLibary/Command.cs b/SharedLibary/Command.cs new file mode 100644 index 00000000..e35932aa --- /dev/null +++ b/SharedLibary/Command.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public abstract class Command + { + public Command(String N, String D, String A, Player.Permission P, int args, bool nT) + { + Name = N; + Description = D; + Alias = A; + Permission = P; + requiredArgNum = args; + needsTarget = nT; + } + + //Execute the command + abstract public void Execute(Event E); + + public String Name { get; private set; } + public String Description { get; private set; } + public String Alias { get; private set; } + public int requiredArgNum { get; private set; } + public bool needsTarget { get; private set; } + public Player.Permission Permission { get; private set; } + } +} diff --git a/SharedLibary/Database.cs b/SharedLibary/Database.cs new file mode 100644 index 00000000..72c84587 --- /dev/null +++ b/SharedLibary/Database.cs @@ -0,0 +1,630 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data.SQLite; +using System.Data; +using System.IO; +using System.Collections; + +namespace SharedLibrary +{ + public abstract class Database + { + public Database(String FN) + { + FileName = FN; + DBCon = String.Format("Data Source={0}", FN); + try + { + Con = new SQLiteConnection(DBCon); + } + + catch(System.DllNotFoundException) + { + Console.WriteLine("Could not locate the SQLite DLL!\nEnsure it is located in the 'lib' folder"); + Utilities.Wait(5); + System.Environment.Exit(0); + } + + Open = false; + Init(); + } + + abstract public void Init(); + + protected bool Insert(String tableName, Dictionary data) + { + String columns = ""; + String values = ""; + Boolean returnCode = true; + foreach (KeyValuePair val in data) + { + columns += String.Format(" {0},", val.Key); + values += String.Format(" '{0}',", val.Value); + } + columns = columns.Substring(0, columns.Length - 1); + values = values.Substring(0, values.Length - 1); + try + { + this.ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values)); + } + catch (Exception fail) + { + Console.WriteLine(fail.Message); + returnCode = false; + } + return returnCode; + } + + protected bool Update(String tableName, Dictionary data, String where) + { + String vals = ""; + Boolean returnCode = true; + if (data.Count >= 1) + { + foreach (KeyValuePair val in data) + { + vals += String.Format(" {0} = '{1}',", val.Key, val.Value); + } + vals = vals.Substring(0, vals.Length - 1); + } + try + { + ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where)); + } + catch (Exception fail) + { + Console.WriteLine(fail.Message); + returnCode = false; + } + return returnCode; + } + + protected DataRow getDataRow(String Q) + { + DataRow Result = GetDataTable(Q).Rows[0]; + return Result; + } + + protected int ExecuteNonQuery(String Request) + { + waitForClose(); + int rowsUpdated = 0; + + lock (Con) + { + Con.Open(); + SQLiteCommand CMD = new SQLiteCommand(Con); + CMD.CommandText = Request; + rowsUpdated = CMD.ExecuteNonQuery(); + Con.Close(); + } + + return rowsUpdated; + } + + protected DataTable GetDataTable(String sql) + { + DataTable dt = new DataTable(); + try + { + waitForClose(); + lock (Con) + { + Con.Open(); + SQLiteCommand mycommand = new SQLiteCommand(Con); + mycommand.CommandText = sql; + SQLiteDataReader reader = mycommand.ExecuteReader(); + dt.Load(reader); + reader.Close(); + Con.Close(); + } + + } + catch (Exception e) + { + Console.WriteLine(e.Message); + throw new Exception(e.Message); + } + return dt; + } + + protected void waitForClose() + { + while (Con.State == ConnectionState.Open) + { + Utilities.Wait(0.01); + } + + return; + } + + protected String FileName; + protected String DBCon; + protected SQLiteConnection Con; + protected bool Open; + } + + public class ClientsDB : Database + { + public ClientsDB(String FN) : base(FN) { } + + public override void Init() + { + if (!File.Exists(FileName)) + { + String Create = "CREATE TABLE [CLIENTS] ( [Name] TEXT NULL, [npID] TEXT NULL, [Number] INTEGER PRIMARY KEY AUTOINCREMENT, [Level] INT DEFAULT 0 NULL, [LastOffense] TEXT NULL, [Connections] INT DEFAULT 1 NULL, [IP] TEXT NULL, [LastConnection] TEXT NULL);"; + ExecuteNonQuery(Create); + Create = "CREATE TABLE [BANS] ( [Reason] TEXT NULL, [npID] TEXT NULL, [bannedByID] TEXT NULL, [IP] TEXT NULL, [TIME] TEXT NULL);"; + ExecuteNonQuery(Create); + } + } + + //Returns a single player object with matching GUID, false if no matches + public Player getPlayer(String ID, int cNum) + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE npID = '{0}' LIMIT 1", ID); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + DataRow ResponseRow = Result.Rows[0]; + DateTime LC; + + try + { + LC = DateTime.Parse(ResponseRow["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } + + return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), LC); + } + + else + return null; + } + + //Overloaded method for getPlayer, returns Client with matching DBIndex, null if none found + public Player getPlayer(int dbIndex) + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE Number = '{0}' LIMIT 1", dbIndex); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + DataRow p = Result.Rows[0]; + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } + + return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC); + } + + else + return null; + } + + //get player by ip, (used for webfront) + public Player getPlayer(String IP) + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE IP='{0}'", IP); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + List lastKnown = new List(); + foreach (DataRow p in Result.Rows) + { + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + lastKnown.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32((DateTime.Now - LC).TotalSeconds), p["IP"].ToString(), LC)); + } + + catch (Exception) + { + continue; + } + } + + if (lastKnown.Count > 0) + { + List Returning = lastKnown.OrderBy(t => t.Connections).ToList(); + return Returning[0]; + } + + else + return null; + } + + else + return null; + } + + //Returns a list of players matching name parameter, null if no players found matching + public List findPlayers(String name) + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE Name LIKE '%{0}%' LIMIT 8", name); + DataTable Result = GetDataTable(Query); + + List Players = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow p in Result.Rows) + { + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + } + catch (Exception) + { + LC = DateTime.Now; + } + + Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC)); + } + return Players; + } + + else + return null; + } + + //Returns any player with level 4 permissions, null if no owner found + public Player getOwner() + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE Level > '{0}'", 4); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + DataRow ResponseRow = Result.Rows[0]; + if (ResponseRow["IP"].ToString().Length < 6) + ResponseRow["IP"] = "0"; + return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), null, 0, ResponseRow["IP"].ToString()); + } + + else + return null; + } + + //Returns list of bans in database + public List getBans() + { + List Bans = new List(); + DataTable Result = GetDataTable("SELECT * FROM BANS ORDER BY TIME DESC"); + + foreach (DataRow Row in Result.Rows) + { + if (Row["TIME"].ToString().Length < 2) //compatibility with my old database + Row["TIME"] = DateTime.Now.ToString(); + + Bans.Add(new Ban(Row["Reason"].ToString(), Row["npID"].ToString(), Row["bannedByID"].ToString(), DateTime.Parse(Row["TIME"].ToString()), Row["IP"].ToString())); + } + + return Bans; + } + + //Returns all players with level > Flagged + public List getAdmins() + { + List Admins = new List(); + String Query = String.Format("SELECT * FROM CLIENTS WHERE LEVEL > '{0}'", 1); + DataTable Result = GetDataTable(Query); + + foreach (DataRow P in Result.Rows) + Admins.Add(new Player(P["Name"].ToString(), P["npID"].ToString(), (Player.Permission)P["Level"], P["IP"].ToString())); + + return Admins; + } + + //Returns total number of player entries in database + public int totalPlayers() + { + DataTable Result = GetDataTable("SELECT * from CLIENTS ORDER BY Number DESC LIMIT 1"); + if (Result.Rows.Count > 0) + return Convert.ToInt32(Result.Rows[0]["Number"]); + else + return 0; + } + + //Add specified player to database + public void addPlayer(Player P) + { + Dictionary newPlayer = new Dictionary(); + + newPlayer.Add("Name", Utilities.removeNastyChars(P.Name)); + newPlayer.Add("npID", P.npID); + newPlayer.Add("Level", (int)P.Level); + newPlayer.Add("LastOffense", ""); + newPlayer.Add("Connections", 1); + newPlayer.Add("IP", P.IP); + newPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); + + Insert("CLIENTS", newPlayer); + } + + ///Update information of specified player + public void updatePlayer(Player P) + { + Dictionary updatedPlayer = new Dictionary(); + + updatedPlayer.Add("Name", P.Name); + updatedPlayer.Add("npID", P.npID); + updatedPlayer.Add("Level", (int)P.Level); + updatedPlayer.Add("LastOffense", P.lastOffense); + updatedPlayer.Add("Connections", P.Connections); + updatedPlayer.Add("IP", P.IP); + updatedPlayer.Add("LastConnection", Utilities.DateTimeSQLite(DateTime.Now)); + + Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.npID)); + } + + + //Add specified ban to database + public void addBan(Ban B) + { + Dictionary newBan = new Dictionary(); + + newBan.Add("Reason", B.Reason); + newBan.Add("npID", B.npID); + newBan.Add("bannedByID", B.bannedByID); + newBan.Add("IP", B.IP); + newBan.Add("TIME", Utilities.DateTimeSQLite(DateTime.Now)); + + Insert("BANS", newBan); + } + + + //Deletes ban with matching GUID + public void removeBan(String GUID) + { + String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}'", GUID); + ExecuteNonQuery(Query); + } + + public void removeBan(String GUID, String IP) + { + String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}' or IP= '%{1}%'", GUID, IP); + ExecuteNonQuery(Query); + } + } + + public class StatsDB : Database + { + public StatsDB(String FN) : base(FN) { } + + public override void Init() + { + if (!File.Exists(FileName)) + { + String Create = "CREATE TABLE [STATS] ( [Number] INTEGER, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] REAL DEFAULT 0, [SKILL] REAL DEFAULT 0, [MEAN] REAL DEFAULT 0, [DEV] REAL DEFAULT 0 );"; + ExecuteNonQuery(Create); + } + } + + // Return stats for player specified by Database ID, null if no matches + public Stats getStats(int DBID) + { + String Query = String.Format("SELECT * FROM STATS WHERE Number = '{0}'", DBID); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + DataRow ResponseRow = Result.Rows[0]; + if (ResponseRow["MEAN"] == DBNull.Value) + ResponseRow["MEAN"] = 0; // Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.Mean; + if (ResponseRow["DEV"] == DBNull.Value) + ResponseRow["DEV"] = 0; // Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.StandardDeviation; + if (ResponseRow["SKILL"] == DBNull.Value) + ResponseRow["SKILL"] = 0; + + return new Stats(Convert.ToInt32(ResponseRow["Number"]), Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["SKILL"]), Convert.ToDouble(ResponseRow["MEAN"]), Convert.ToDouble(ResponseRow["DEV"])); + } + + else + return null; + } + + public void addPlayer(Player P) + { + Dictionary newPlayer = new Dictionary(); + + newPlayer.Add("Number", P.databaseID); + newPlayer.Add("KILLS", 0); + newPlayer.Add("DEATHS", 0); + newPlayer.Add("KDR", 0); + newPlayer.Add("SKILL", 0); //Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.ConservativeRating); + newPlayer.Add("MEAN", 0); //Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.Mean); + newPlayer.Add("DEV", 0); //Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.StandardDeviation); + + Insert("STATS", newPlayer); + } + + //Update stat information of specified player + public void updatePlayer(Player P) + { + if (P.stats == null) + return; + + Dictionary updatedPlayer = new Dictionary(); + + updatedPlayer.Add("KILLS", P.stats.Kills); + updatedPlayer.Add("DEATHS", P.stats.Deaths); + updatedPlayer.Add("KDR", Math.Round(P.stats.KDR, 2)); + updatedPlayer.Add("SKILL", P.stats.Skill); + //updatedPlayer.Add("MEAN", P.stats.Rating.Mean); + //updatedPlayer.Add("DEV", P.stats.Rating.StandardDeviation); + + Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.databaseID)); + } + + //Returns top 5 players (we filter through them later) + public List topStats() + { + String Query = String.Format("SELECT * FROM STATS WHERE KILLS > '{0}' AND KDR < '{1}' AND SKILL > '{2}' ORDER BY SKILL DESC LIMIT 5", 250, 7, 245); + DataTable Result = GetDataTable(Query); + + List Top = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow D in Result.Rows) + { + if (D["MEAN"] == DBNull.Value || D["DEV"] == DBNull.Value || D["SKILL"] == DBNull.Value) + continue; + + Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["KILLS"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]), Convert.ToDouble(D["MEAN"]), Convert.ToDouble(D["DEV"])); + Top.Add(S); + } + } + + return Top; + } + + public List getMultipleStats(int start, int length) + { + String Query = String.Format("SELECT * FROM STATS ORDER BY SKILL DESC LIMIT '{0}' OFFSET '{1}'", length, start); + DataTable Result = GetDataTable(Query); + + List Stats = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow D in Result.Rows) + { + if (D["MEAN"] == DBNull.Value) + continue; + if (D["DEV"] == DBNull.Value) + continue; + + if (D["SKILL"] == DBNull.Value) + D["SKILL"] = 0; + + Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["KILLS"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]), Convert.ToDouble(D["MEAN"]), Convert.ToDouble(D["DEV"])); + Stats.Add(S); + } + } + + return Stats; + } + + public int totalStats() + { + DataTable Result = GetDataTable("SELECT * FROM STATS"); + return Result.Rows.Count; + } + + public void clearSkill() + { + String Query = "SELECT * FROM STATS"; + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow D in Result.Rows) + Update("STATS", new Dictionary() { { "SKILL", 1 } }, String.Format("Number = '{0}'", D["Number"])); + } + } + } + + public class AliasesDB : Database + { + public AliasesDB(String FN) : base(FN) { } + + public override void Init() + { + if (!File.Exists(FileName)) + { + String Create = "CREATE TABLE [ALIASES] ( [Number] INTEGER, [NAMES] TEXT NULL, [IPS] TEXTNULL );"; + ExecuteNonQuery(Create); + } + } + + public Aliases getPlayer(int dbIndex) + { + String Query = String.Format("SELECT * FROM ALIASES WHERE Number = '{0}' LIMIT 1", dbIndex); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + DataRow p = Result.Rows[0]; + return new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString()); + } + + else + return null; + } + + public List getPlayer(String IP) + { + String Query = String.Format("SELECT * FROM ALIASES WHERE IPS LIKE '%{0}%'", IP); + DataTable Result = GetDataTable(Query); + List players = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow p in Result.Rows) + players.Add(new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString())); + } + + return players; + } + + public List findPlayers(String name) + { + String[] EyePee = name.Split('.'); + String Penor = "THISISNOTANIP"; + if (EyePee.Length > 1) + Penor = (EyePee[0] + '.' + EyePee[1] + '.'); + + String Query = String.Format("SELECT * FROM ALIASES WHERE NAMES LIKE '%{0}%' OR IPS LIKE '%{1}%' LIMIT 15", name, Penor); + DataTable Result = GetDataTable(Query); + + List players = new List(); + + if (Result != null && Result.Rows.Count > 0) + { + foreach (DataRow p in Result.Rows) + players.Add(new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString())); + } + + return players; + } + + public void addPlayer(Aliases Alias) + { + Dictionary newPlayer = new Dictionary(); + + newPlayer.Add("Number", Alias.getNumber()); + newPlayer.Add("NAMES", Alias.getNamesDB()); + newPlayer.Add("IPS", Alias.getIPSDB()); + + Insert("ALIASES", newPlayer); + } + + public void updatePlayer(Aliases Alias) + { + Dictionary updatedPlayer = new Dictionary(); + + updatedPlayer.Add("Number", Alias.getNumber()); + updatedPlayer.Add("NAMES", Alias.getNamesDB()); + updatedPlayer.Add("IPS", Alias.getIPSDB()); + + Update("ALIASES", updatedPlayer, String.Format("Number = '{0}'", Alias.getNumber())); + } + } +} diff --git a/SharedLibary/Dvar.cs b/SharedLibary/Dvar.cs new file mode 100644 index 00000000..7a33448a --- /dev/null +++ b/SharedLibary/Dvar.cs @@ -0,0 +1,19 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SharedLibrary +{ + public struct dvar + { + public String name; + public String description; + public int flags; + public short type; + public String current; + public String latched; + public String _default; + public int min; + public int max; + } +} diff --git a/Admin/Event.cs b/SharedLibary/Event.cs similarity index 84% rename from Admin/Event.cs rename to SharedLibary/Event.cs index 38ed3dcf..57a694bc 100644 --- a/Admin/Event.cs +++ b/SharedLibary/Event.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; -namespace IW4MAdmin +namespace SharedLibrary { - class Chat + public class Chat { - public Chat ( Player O, String M, DateTime D) + public Chat(Player O, String M, DateTime D) { Origin = O; Message = M; @@ -24,7 +24,7 @@ namespace IW4MAdmin public DateTime Time { get; private set; } } - class Event + public class Event { public enum GType { @@ -36,13 +36,12 @@ namespace IW4MAdmin Death, MapChange, MapEnd, - + //FROM ADMIN Broadcast, Tell, Kick, - Ban, - + Ban, Unknown, } @@ -55,7 +54,6 @@ namespace IW4MAdmin Owner = S; } - //This needs to be here public Command isValidCMD(List list) { if (this.Data.Substring(0, 1) == "!") @@ -64,7 +62,7 @@ namespace IW4MAdmin foreach (Command C in list) { - if (C.getName() == cmd[0].ToLower() || C.getAlias() == cmd[0].ToLower()) + if (C.Name == cmd[0].ToLower() || C.Alias == cmd[0].ToLower()) return C; } @@ -91,7 +89,7 @@ namespace IW4MAdmin return new Event(GType.Disconnect, null, SV.clientFromEventLine(line, 2), null, SV); if (eventType == "K") - return new Event(GType.Kill, line[9], SV.clientFromEventLine(line, 6), SV.clientFromEventLine(line, 2), SV); + return new Event(GType.Kill, line[9], SV.clientFromEventLine(line, 6), SV.clientFromEventLine(line, 2), SV); if (line[0].Substring(line[0].Length - 3).Trim() == "say") { @@ -100,8 +98,8 @@ namespace IW4MAdmin return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromEventLine(line, 2), null, SV); } - if (eventType == ":") - return new Event(GType.MapEnd, line[0], new Player("WORLD", "WORLD", 0, 0), null, null); + if (eventType == ":") + return new Event(GType.MapEnd, line[0], new Player("WORLD", "WORLD", 0, 0), null, null); if (line[0].Split('\\').Length > 5) // blaze it return new Event(GType.MapChange, line[0], new Player("WORLD", "WORLD", 0, 0), null, null); @@ -124,6 +122,5 @@ namespace IW4MAdmin public Player Origin; public Player Target; public Server Owner; - } } diff --git a/SharedLibary/File.cs b/SharedLibary/File.cs new file mode 100644 index 00000000..24dbc120 --- /dev/null +++ b/SharedLibary/File.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace SharedLibrary +{ + public class IFile + { + public IFile(String fileName) + { + //Not safe for directories with more than one folder but meh + _Directory = fileName.Split('\\')[0]; + Name = (fileName.Split('\\'))[fileName.Split('\\').Length - 1]; + + if (!Directory.Exists(_Directory)) + Directory.CreateDirectory(_Directory); + + if (!File.Exists(fileName)) + { + try + { + FileStream penis = File.Create(fileName); + penis.Close(); + } + + catch + { + Console.WriteLine("Unable to create file!"); + } + } + + try + { + Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + sze = Handle.BaseStream.Length; + } + + catch + { + //Console.WriteLine("Unable to open log file for writing!"); + } + } + + public IFile(String file, bool write) + { + Name = file; + writeHandle = new StreamWriter(new FileStream(Name, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)); + sze = 0; + } + + public long getSize() + { + sze = Handle.BaseStream.Length; + return sze; + } + + public void Write(String line) + { + if (writeHandle != null) + { + writeHandle.WriteLine(line); + writeHandle.Flush(); + } + } + + public String[] getParameters(int num) + { + if (sze > 0) + { + String firstLine = Handle.ReadLine(); + String[] Parms = firstLine.Split(':'); + if (Parms.Length < num) + return null; + else + return Parms; + } + + return null; + } + + public void Close() + { + if (Handle != null) + Handle.Close(); + if (writeHandle != null) + writeHandle.Close(); + } + + public String[] readAll() + { + return Handle.ReadToEnd().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + + public String getLines() + { + return Handle.ReadToEnd(); + } + + public String[] Tail(int lineCount) + { + var buffer = new List(lineCount); + string line; + for (int i = 0; i < lineCount; i++) + { + line = Handle.ReadLine(); + if (line == null) return buffer.ToArray(); + buffer.Add(line); + } + + int lastLine = lineCount - 1; //The index of the last line read from the buffer. Everything > this index was read earlier than everything <= this indes + + while (null != (line = Handle.ReadLine())) + { + lastLine++; + if (lastLine == lineCount) lastLine = 0; + buffer[lastLine] = line; + } + + if (lastLine == lineCount - 1) return buffer.ToArray(); + var retVal = new string[lineCount]; + buffer.CopyTo(lastLine + 1, retVal, 0, lineCount - lastLine - 1); + buffer.CopyTo(0, retVal, lineCount - lastLine - 1, lastLine + 1); + return retVal; + } + //END + + private long sze; + private String Name; + private String _Directory; + private StreamReader Handle; + private StreamWriter writeHandle; + } +} diff --git a/SharedLibary/Log.cs b/SharedLibary/Log.cs new file mode 100644 index 00000000..41ac1312 --- /dev/null +++ b/SharedLibary/Log.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public class Log + { + public enum Level + { + All, + Debug, + Production, + None, + } + + public Log(IFile logf, Level mode, int port) + { + logFile = logf; + logMode = mode; + Identifier = port; + } + + public void Write(String line) + { + Write(line, Level.Debug); + } + + public void Write(String line, Level lv) + { + String Line = String.Format("{1} - [{0}]: {2}", Identifier, getTime(), line); + switch (logMode) + { + case Level.All: + if (lv == Level.All || lv == Level.Debug || lv == Level.Production) + Console.WriteLine(Line); + break; + case Level.Debug: + if (lv == Level.All || lv == Level.Debug) + Console.WriteLine(Line); + break; + case Level.Production: + if (lv == Level.Production) + Console.WriteLine(Line); + break; + } + + logFile.Write(Line); + } + + private string getTime() + { + return DateTime.Now.ToString("HH:mm:ss"); + } + + private IFile logFile; + private Level logMode; + private int Identifier; + } +} diff --git a/SharedLibary/Map.cs b/SharedLibary/Map.cs new file mode 100644 index 00000000..4b588691 --- /dev/null +++ b/SharedLibary/Map.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public class Map + { + public Map(String N, String A) + { + Name = N; + Alias = A; + } + + public String Name { get; private set; } + public String Alias { get; private set; } + } +} diff --git a/SharedLibary/Player.cs b/SharedLibary/Player.cs new file mode 100644 index 00000000..84652cf4 --- /dev/null +++ b/SharedLibary/Player.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SharedLibrary +{ + public class Stats + { + public Stats(int n, int K, int D, double kdr, double skill, double mean, double dev) + { + statIndex = n; + Kills = K; + Deaths = D; + KDR = Math.Round(kdr, 2); + + //Rating = new Moserware.Skills.Rating(mean, dev); + //Skill = Math.Round(Rating.ConservativeRating, 3) * 10; + + } + + public void updateKDR() + { + int tempDeaths = Deaths; // cuz we don't want undefined! + if (Deaths == 0) + tempDeaths = 1; + + KDR = Math.Round((double)((double)Kills / (double)tempDeaths), 2); + } + + public int Kills; + public int Deaths; + public double KDR; + public double Skill; + public int statIndex; + // public Moserware.Skills.Rating Rating; + } + + public class Aliases + { + public Aliases(int Num, String N, String I) + { + Number = Num; + Names = N; + IPS = I; + } + + public List getNames() + { + return new List(Names.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); + } + + public List getIPS() + { + return new List(IPS.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); + } + + public String getIPSDB() + { + return IPS; + } + + public String getNamesDB() + { + return Names; + } + + public int getNumber() + { + return Number; + } + + public void addName(String Name) + { + if (Name.Trim() != String.Empty && Name != null) + Names += ';' + Name; + } + + public void addIP(String IP) + { + if (IP.Trim() != String.Empty && IP != null) + IPS += ';' + IP; + } + + private String Names; + private String IPS; + private int Number; + } + + public class Player + { + public enum Permission + { + Banned = -1, + User = 0, + Flagged = 1, + Moderator = 2, + Administrator = 3, + SeniorAdmin = 4, + Owner = 5, + Creator = 6, + } + + public Player(string n, string id, int num, int l) + { + Name = n; + npID = id; + clientID = num; + Level = (Player.Permission)l; + lastOffense = String.Empty; + Connections = 0; + IP = ""; + Warnings = 0; + Alias = new Aliases(0, "", ""); + //stats = new Stats(0, 0, 0, 0, Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.ConservativeRating, Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.Mean, Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.StandardDeviation); + LastConnection = DateTime.Now; + + } + + public Player(string n, string id, int num, String I) + { + Name = n; + npID = id; + clientID = num; + IP = I; + LastConnection = DateTime.Now; + } + + public Player(string n, string id, Player.Permission P, String I) + { + Name = n; + npID = id; + Level = P; + IP = I; + } + + 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; + Level = l; + databaseID = cind; + if (lo == null) + lastOffense = String.Empty; + else + lastOffense = lo; + Connections = con; + IP = IP2; + Warnings = 0; + Masked = false; + LastConnection = DateTime.Now; + } + + public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2, DateTime LC) + { + Name = n; + npID = id; + clientID = num; + Level = l; + databaseID = cind; + if (lo == null) + lastOffense = String.Empty; + else + lastOffense = lo; + Connections = con; + IP = IP2; + Warnings = 0; + Masked = false; + LastConnection = LC; + } + + public String getLastConnection() + { + return Utilities.timePassed(LastConnection); + } + + public void updateName(String n) + { + if (n.Trim() != String.Empty) + Name = n; + } + + public void updateIP(String I) + { + IP = I; + } + + public void setLevel(Player.Permission Perm) + { + Level = Perm; + } + + public void Tell(String Message) + { + lastEvent.Owner.Tell(Message, this); + } + + public void Kick(String Message) + { + currentServer.Kick(Message, this); + } + + public void tempBan(String Message) + { + currentServer.tempBan(Message, this); + } + + public void Ban(String Message, Player Sender) + { + currentServer.Ban(Message, this, Sender); + } + + public void Alert() + { + currentServer.Alert(this); + } + + 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 int Connections { get; set; } + public String IP { get; private set; } + public DateTime LastConnection { get; private set; } + public Server currentServer { get; private set; } + + public Event lastEvent; + public String lastOffense; + public int Warnings; + public Stats stats; + public Aliases Alias; + public bool Masked; + } +} diff --git a/SharedLibary/Properties/AssemblyInfo.cs b/SharedLibary/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..97852cc9 --- /dev/null +++ b/SharedLibary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SharedLibary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SharedLibary")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c434bf30-cd8f-4270-a386-e3b970f02f21")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SharedLibary/Report.cs b/SharedLibary/Report.cs new file mode 100644 index 00000000..2575fc6f --- /dev/null +++ b/SharedLibary/Report.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public class Report + { + public Report(Player T, Player O, String R) + { + Target = T; + Origin = O; + Reason = R; + } + + public Player Target { get; private set; } + public Player Origin { get; private set; } + public String Reason { get; private set; } + } +} diff --git a/SharedLibary/Server.cs b/SharedLibary/Server.cs new file mode 100644 index 00000000..4191f24b --- /dev/null +++ b/SharedLibary/Server.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharedLibrary +{ + public abstract class Server + { + public Server(string address, int port, string password, int H, int PID) + { + this.PID = PID; + Handle = H; + IP = address; + Port = port; + clientnum = 0; + logFile = new IFile("admin_" + port + ".log", true); +#if DEBUG + Log = new Log(logFile, Log.Level.Debug, port); +#else + Log = new Log(logFile, Log.Level.Production, port); +#endif + clientDB = new ClientsDB("clients.rm"); + statDB = new StatsDB("stats_" + Port + ".rm"); + aliasDB = new AliasesDB("aliases.rm"); + + players = new List(new Player[18]); + events = new Queue(); + Macros = new Dictionary(); + Reports = new List(); + statusPlayers = new Dictionary(); + chatHistory = new List(); + lastWebChat = DateTime.Now; + nextMessage = 0; + initCommands(); + initMacros(); + initMessages(); + initMaps(); + initRules(); + } + + //Returns the current server name -- *STRING* + public String getName() + { + return hostname; + } + + public String getMap() + { + return mapname; + } + + public String getGametype() + { + return Gametype; + } + + //Returns current server IP set by `net_ip` -- *STRING* + public String getIP() + { + return IP; + } + + //Returns current server port set by `net_port` -- *INT* + public int getPort() + { + return Port; + } + + //Returns number of active clients on server -- *INT* + public int getNumPlayers() + { + return clientnum; + } + + //Returns the list of commands + public List getCommands() + { + return commands; + } + + //Returns list of all current players + public List getPlayers() + { + return players; + } + + public int getClientNum() + { + return clientnum; + } + + public int getMaxClients() + { + return maxClients; + } + + //Returns list of all active bans (loaded at runtime) + public List getBans() + { + return Bans; + } + + public int pID() + { + return this.PID; + } + + abstract public void getAliases(List returnPlayers, Player Origin); + + //Add player object p to `players` list + abstract public bool addPlayer(Player P); + + //Remove player by CLIENT NUMBER + abstract public bool removePlayer(int cNum); + + abstract public Player clientFromEventLine(String[] L, int cIDPos); + + public Player clientFromName(String pName) + { + lock (players) + { + foreach (var P in players) + { + if (P != null && P.Name.ToLower().Contains(pName.ToLower())) + return P; + } + } + + return null; + } + + //Check ban list for every banned player and return ban if match is found + abstract public Ban isBanned(Player C); + + //Procses requested command correlating to an event + abstract public Command processCommand(Event E, Command C); + + //push a new event into the queue + private void addEvent(Event E) + { + events.Enqueue(E); + } + + abstract public void executeCommand(String CMD); + + abstract public dvar getDvar(String DvarName); + + abstract public void setDvar(String Dvar, String Value); + + //Starts the monitoring process + abstract public void Monitor(); + + abstract public bool intializeBasics(); + + //Process any server event + abstract public bool processEvent(Event E); + + public bool Reload() + { + try + { + messages = null; + maps = null; + rules = null; + initMaps(); + initMessages(); + initRules(); + return true; + } + catch (Exception E) + { + Log.Write("Unable to reload configs! - " + E.Message, Log.Level.Debug); + messages = new List(); + maps = new List(); + rules = new List(); + return false; + } + } + + //THESE MAY NEED TO BE MOVED + public void Broadcast(String Message) + { + executeCommand("sayraw " + Message); + } + + public void Tell(String Message, Player Target) + { + if (Target.clientID > -1) + executeCommand("tellraw " + Target.clientID + " " + Message + "^7"); + } + + public void Kick(String Message, Player Target) + { + if (Target.clientID > -1) + executeCommand("clientkick " + Target.clientID + " \"" + Message + "^7\""); + } + + abstract public void Ban(String Message, Player Target, Player Origin); + + abstract public bool Unban(String GUID, Player Target); + + + public void fastRestart(int delay) + { + Utilities.Wait(delay); + executeCommand("fast_restart"); + } + + public void mapRotate(int delay) + { + Utilities.Wait(delay); + executeCommand("map_rotate"); + } + + public void tempBan(String Message, Player Target) + { + executeCommand("tempbanclient " + Target.clientID + " \"" + Message + "\""); + } + + public void mapRotate() + { + mapRotate(0); + } + + public void Map(String mapName) + { + executeCommand("map " + mapName); + } + + public void ToAdmins(String message) + { + lock (players) // threading can modify list while we do this + { + foreach (Player P in players) + { + if (P == null) + continue; + + if (P.Level > Player.Permission.Flagged) + { + P.Alert(); + P.Tell(message); + } + } + } + } + + public void Alert(Player P) + { + executeCommand("admin_lastevent alert;" + P.npID + ";0;mp_killstreak_nuclearstrike"); + } + + public void webChat(Player P, String Message) + { + DateTime requestTime = DateTime.Now; + + if ((requestTime - lastWebChat).TotalSeconds > 1) + { + Broadcast("^1[WEBCHAT] ^5" + P.Name + "^7 - " + Message); + while (chatHistory.Count > Math.Ceiling((double)clientnum / 2)) + chatHistory.RemoveAt(0); + + if (Message.Length > 50) + Message = Message.Substring(0, 50) + "..."; + + chatHistory.Add(new Chat(P, Utilities.stripColors(Message), DateTime.Now)); + lastWebChat = DateTime.Now; + } + } + + abstract public void initMacros(); + + private void initMaps() + { + maps = new List(); + + IFile mapfile = new IFile("config\\maps.cfg"); + String[] _maps = mapfile.readAll(); + mapfile.Close(); + if (_maps.Length > 2) // readAll returns minimum one empty string + { + foreach (String m in _maps) + { + String[] m2 = m.Split(':'); + if (m2.Length > 1) + { + Map map = new Map(m2[0].Trim(), m2[1].Trim()); + maps.Add(map); + } + } + } + else + Log.Write("Maps configuration appears to be empty - skipping...", Log.Level.All); + } + + private void initMessages() + { + messages = new List(); + + IFile messageCFG = new IFile("config\\messages.cfg"); + String[] lines = messageCFG.readAll(); + messageCFG.Close(); + + if (lines.Length < 2) //readAll returns minimum one empty string + { + Log.Write("Messages configuration appears empty - skipping...", Log.Level.All); + return; + } + + int mTime = -1; + int.TryParse(lines[0], out mTime); + + if (messageTime == -1) + messageTime = 60; + else + messageTime = mTime; + + foreach (String l in lines) + { + if (lines[0] != l && l.Length > 1) + messages.Add(l); + } + + messageCFG.Close(); + + //if (Program.Version != Program.latestVersion && Program.latestVersion != 0) + // messages.Add("^5IW4M Admin ^7is outdated. Please ^5update ^7to version " + Program.latestVersion); + } + + private void initRules() + { + rules = new List(); + + IFile ruleFile = new IFile("config\\rules.cfg"); + String[] _rules = ruleFile.readAll(); + ruleFile.Close(); + if (_rules.Length > 2) // readAll returns minimum one empty string + { + foreach (String r in _rules) + { + if (r.Length > 1) + rules.Add(r); + } + } + else + Log.Write("Rules configuration appears empty - skipping...", Log.Level.All); + + ruleFile.Close(); + } + + abstract public void initCommands(); + abstract public void initAbstractObj(); + + //Objects + public Log Log; + public List Bans; + public Player owner; + public List maps; + public List rules; + public Queue events; + public String Website; + public String Gametype; + public int totalKills = 0; + public List Reports; + public List chatHistory; + + //Info + protected String IP; + protected int Port; + protected String hostname; + protected String mapname; + protected int clientnum; + protected List players; + protected List commands; + protected List messages; + protected int messageTime; + protected TimeSpan lastMessage; + protected DateTime lastPoll; + protected int nextMessage; + protected String IW_Ver; + protected int maxClients; + protected Dictionary Macros; + protected DateTime lastWebChat; + protected int Handle; + protected int PID; + protected IFile logFile; + + // Will probably move this later + public Dictionary statusPlayers; + public bool isRunning; + + // Log stuff + protected String Basepath; + protected String Mod; + protected String logPath; + + // Databases + public ClientsDB clientDB; + public AliasesDB aliasDB; + public StatsDB statDB; + } +} diff --git a/SharedLibary/SharedLibrary.csproj b/SharedLibary/SharedLibrary.csproj new file mode 100644 index 00000000..b7d35dde --- /dev/null +++ b/SharedLibary/SharedLibrary.csproj @@ -0,0 +1,72 @@ + + + + + Debug + AnyCPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6} + Library + Properties + SharedLibrary + SharedLibary + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + ..\..\Admin\lib\System.Data.SQLite.dll + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SharedLibary/SharedLibrary.sln b/SharedLibary/SharedLibrary.sln new file mode 100644 index 00000000..a7ca4c01 --- /dev/null +++ b/SharedLibary/SharedLibrary.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedLibrary", "SharedLibrary.csproj", "{D51EECEB-438A-47DA-870F-7D7B41BC24D6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SharedLibary/Utilities.cs b/SharedLibary/Utilities.cs new file mode 100644 index 00000000..249529f0 --- /dev/null +++ b/SharedLibary/Utilities.cs @@ -0,0 +1,243 @@ +using System; +using System.Threading; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections.Generic; + +namespace SharedLibrary +{ + class Utilities + { + //Get string with specified number of spaces -- really only for visual output + public static String getSpaces(int Num) + { + String SpaceString = String.Empty; + while (Num > 0) + { + SpaceString += ' '; + Num--; + } + + return SpaceString; + } + + //Sleep for x amount of seconds + public static void Wait(double time) + { + Thread.Sleep((int)Math.Ceiling(time * 1000)); + } + + //Remove words from a space delimited string + public static String removeWords(String str, int num) + { + String newStr = String.Empty; + String[] tmp = str.Split(' '); + + for (int i = 0; i < tmp.Length; i++) + { + if (i >= num) + newStr += tmp[i] + ' '; + } + + return newStr; + } + + public static Player.Permission matchPermission(String str) + { + String lookingFor = str.ToLower(); + + for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Owner; Perm++) + { + if (lookingFor.Contains(Perm.ToString().ToLower())) + return Perm; + } + + return Player.Permission.Banned; + } + + public static String removeNastyChars(String str) + { + if (str != null) + return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace(""", "''").Replace("&", "&").Replace("\"", "''"); + else + return String.Empty; + } + + public static int GetLineNumber(Exception ex) + { + var lineNumber = 0; + const string lineSearch = ":line "; + var index = ex.StackTrace.LastIndexOf(lineSearch); + if (index != -1) + { + var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length); + if (int.TryParse(lineNumberText, out lineNumber)) + { + } + } + return lineNumber; + } + + public static String cleanChars(String S) + { + if (S == null) + return ""; + + StringBuilder Cleaned = new StringBuilder(); + + foreach (char c in S) + if (c < 127 && c > 31 && c != 37 && c != 34 && c != 92) Cleaned.Append(c); + return Cleaned.ToString(); + } + + public static String stripColors(String str) + { + if (str == null) + return ""; + return Regex.Replace(str, @"\^[0-9]", ""); + } + + public static String levelToColor(Player.Permission level) + { + switch (level) + { + case Player.Permission.Banned: + return "^1" + Player.Permission.Banned; + case Player.Permission.Flagged: + return "^0" + Player.Permission.Flagged; + case Player.Permission.Owner: + return "^5" + Player.Permission.Owner; + case Player.Permission.User: + return "^2" + Player.Permission.User; + default: + return "^3" + level; + } + } + + public static String processMacro(Dictionary Dict, String str) + { + MatchCollection Found = Regex.Matches(str, @"\{\{[A-Z]+\}\}", RegexOptions.IgnoreCase); + foreach (Match M in Found) + { + String Match = M.Value; + String Identifier = M.Value.Substring(2, M.Length - 4); + String Replacement = Dict[Identifier].ToString(); + str = str.Replace(Match, Replacement); + } + + return str; + } + + public static String gametypeLocalized(String input) + { + switch (input) + { + case "dm": + return "Deathmatch"; + case "war": + return "Team Deathmatch"; + case "koth": + return "Headquarters"; + case "ctf": + return "Capture The Flag"; + case "dd": + return "Demolition"; + case "dom": + return "Domination"; + case "sab": + return "Sabotage"; + case "sd": + return "Search & Destroy"; + case "vip": + return "Very Important Person"; + case "gtnw": + return "Global Thermonuclear War"; + case "oitc": + return "One In The Chamber"; + case "arena": + return "Arena"; + case "dzone": + return "Drop Zone"; + case "gg": + return "Gun Game"; + case "snipe": + return "Sniping"; + case "ss": + return "Sharp Shooter"; + case "m40a3": + return "M40A3"; + case "fo": + return "Face Off"; + case "dmc": + return "Deathmatch Classic"; + case "killcon": + return "Kill Confirmed"; + case "oneflag": + return "One Flag CTF"; + default: + return "Unknown"; + } + } + + public static String DateTimeSQLite(DateTime datetime) + { + string dateTimeFormat = "{0}-{1}-{2} {3}:{4}:{5}.{6}"; + return string.Format(dateTimeFormat, datetime.Year, datetime.Month, datetime.Day, datetime.Hour, datetime.Minute, datetime.Second, datetime.Millisecond); + } + + public static String timePassed(DateTime start) + { + TimeSpan Elapsed = DateTime.Now - start; + + if (Elapsed.TotalMinutes < 120) + return Math.Round(Elapsed.TotalMinutes, 0) + " minutes"; + if (Elapsed.TotalHours <= 24) + return Math.Round(Elapsed.TotalHours, 0) + " hours"; + if (Elapsed.TotalDays <= 365) + return Math.Round(Elapsed.TotalDays, 0) + " days"; + else + return "a very long time"; + } + + public static String timesConnected(int connection) + { + String Prefix = String.Empty; + if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19)) + Prefix = "th"; + else + { + switch (connection % 10) + { + case 1: + Prefix = "st"; + break; + case 2: + Prefix = "nd"; + break; + case 3: + Prefix = "rd"; + break; + } + } + + switch (connection) + { + case 0: + case 1: + return "first"; + case 2: + return "second"; + case 3: + return "third"; + case 4: + return "fourth"; + case 5: + return "fifth"; + case 100: + return "One-Hundreth (amazing!)"; + default: + return connection.ToString() + Prefix; + } + } + } +}