-close config files after reading oops
-added reload command -added macros! (Denoted by {{MACRO}} in server config right now only {{WISDOM}} and {{TOTALPLAYERS}}) -added IP's (tracks and rebans new accounts on same banned ip)! -aliases -reworked database classes -heartbeat gives running version -player banned in find gives last ban reason -reworked rcon yet again
This commit is contained in:
parent
ef80a565cb
commit
73dfb9a612
@ -6,12 +6,13 @@ namespace IW4MAdmin
|
||||
{
|
||||
class Ban
|
||||
{
|
||||
public Ban(String Reas, String TargID, String From)
|
||||
public Ban(String Reas, String TargID, String From, DateTime time, String ip)
|
||||
{
|
||||
Reason = Reas;
|
||||
npID = TargID;
|
||||
bannedByID = From;
|
||||
When = DateTime.Now;
|
||||
When = time;
|
||||
IP = ip;
|
||||
}
|
||||
|
||||
public String getReason()
|
||||
@ -29,10 +30,21 @@ namespace IW4MAdmin
|
||||
return bannedByID;
|
||||
}
|
||||
|
||||
public String getIP()
|
||||
{
|
||||
return IP;
|
||||
}
|
||||
|
||||
public String getWhen()
|
||||
{
|
||||
return When.ToString("yyyy-MM-dd HH:mm:ss"); ;
|
||||
}
|
||||
|
||||
private String Reason;
|
||||
private String npID;
|
||||
private String bannedByID;
|
||||
private DateTime When;
|
||||
private String IP;
|
||||
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ namespace IW4MAdmin
|
||||
E.Origin.setLevel(Player.Permission.Owner);
|
||||
E.Origin.Tell("Congratulations, you have claimed ownership of this server!");
|
||||
E.Owner.owner = E.Origin;
|
||||
E.Owner.DB.updatePlayer(E.Origin);
|
||||
E.Owner.clientDB.updatePlayer(E.Origin);
|
||||
}
|
||||
else
|
||||
E.Origin.Tell("This server already has an owner!");
|
||||
@ -168,15 +168,10 @@ namespace IW4MAdmin
|
||||
E.Target.LastOffense = Utilities.removeWords(E.Data, 1);
|
||||
E.Target.lastEvent = E; // needs to be fixed
|
||||
String Message;
|
||||
#if DEBUG
|
||||
Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal at nbsclan.org)";
|
||||
#else
|
||||
if (E.Owner.Website == null)
|
||||
Message = "^1Player Banned: ^5" + E.Target.LastOffense;
|
||||
else
|
||||
Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal at " + E.Owner.Website + ")";
|
||||
|
||||
#endif
|
||||
if (E.Origin.getLevel() > E.Target.getLevel())
|
||||
{
|
||||
E.Target.Ban(Message, E.Origin);
|
||||
@ -324,7 +319,7 @@ namespace IW4MAdmin
|
||||
E.Target.Tell("Congratulations! You have been promoted to ^3" + newPerm);
|
||||
E.Origin.Tell(E.Target.getName() + " was successfully promoted!");
|
||||
//NEEED TO MOVE
|
||||
E.Owner.DB.updatePlayer(E.Target);
|
||||
E.Owner.clientDB.updatePlayer(E.Target);
|
||||
}
|
||||
|
||||
else
|
||||
@ -379,8 +374,7 @@ namespace IW4MAdmin
|
||||
|
||||
public override void Execute(Event E)
|
||||
{
|
||||
String Quote = new Connection("http://www.iheartquotes.com/api/v1/random?max_lines=1&max_characters=200").Read();
|
||||
E.Owner.Broadcast(Utilities.removeNastyChars(Quote));
|
||||
E.Owner.Broadcast(E.Owner.Wisdom());
|
||||
}
|
||||
|
||||
}
|
||||
@ -417,16 +411,32 @@ namespace IW4MAdmin
|
||||
|
||||
public override void Execute(Event E)
|
||||
{
|
||||
var db_players = E.Owner.DB.findPlayers(E.Data.Trim());
|
||||
var db_players = E.Owner.clientDB.findPlayers(E.Data.Trim());
|
||||
if (db_players == null)
|
||||
{
|
||||
E.Origin.Tell("No players found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (Player P in db_players)
|
||||
{
|
||||
String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2} [{3}^7]", P.getName(), P.getDBID(), P.getID(), Utilities.levelToColor(P.getLevel()));
|
||||
String mesg;
|
||||
var db_aliases = E.Owner.aliasDB.getPlayer(P.getDBID());
|
||||
|
||||
if (P.getLevel() == Player.Permission.Banned)
|
||||
mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2} [{3}^7] - {4}", P.getName(), P.getDBID(), P.getID(), Utilities.levelToColor(P.getLevel()), P.getLastO());
|
||||
else
|
||||
mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2} [{3}^7]", P.getName(), P.getDBID(), P.getID(), Utilities.levelToColor(P.getLevel()));
|
||||
E.Origin.Tell(mesg);
|
||||
if (db_aliases != null)
|
||||
{
|
||||
mesg = "Aliases: ";
|
||||
foreach (String S in db_aliases.getNames())
|
||||
mesg += S + ',';
|
||||
}
|
||||
|
||||
E.Origin.Tell(mesg);
|
||||
}
|
||||
|
||||
@ -458,7 +468,7 @@ namespace IW4MAdmin
|
||||
public override void Execute(Event E)
|
||||
{
|
||||
E.Target.Tell("^1" + E.Origin.getName() + " ^3[PM]^7 - " + E.Data);
|
||||
E.Origin.Tell("Sucessfully sent message");
|
||||
E.Origin.Tell(String.Format("To ^3{0} ^7-> {1}", E.Target.getName(), E.Data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,7 +483,7 @@ namespace IW4MAdmin
|
||||
else
|
||||
{
|
||||
if (E.Target.stats == null)
|
||||
E.Target.stats = E.Owner.stats.getStats(E.Target.getDBID());
|
||||
E.Target.stats = E.Owner.statDB.getStats(E.Target.getDBID());
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@ -485,12 +495,12 @@ namespace IW4MAdmin
|
||||
|
||||
public override void Execute(Event E)
|
||||
{
|
||||
List<Stats> Top = E.Owner.stats.topStats();
|
||||
List<Stats> Top = E.Owner.statDB.topStats();
|
||||
List<Player> TopP = new List<Player>();
|
||||
|
||||
foreach (Stats S in Top)
|
||||
{
|
||||
Player P = E.Owner.DB.findPlayers(S.Kills); // BAD
|
||||
Player P = E.Owner.clientDB.getPlayer(S.Kills); // BAD
|
||||
if (P != null && P.getLevel() != Player.Permission.Banned)
|
||||
{
|
||||
P.stats = S;
|
||||
@ -512,5 +522,18 @@ namespace IW4MAdmin
|
||||
}
|
||||
}
|
||||
|
||||
class Reload : Command
|
||||
{
|
||||
public Reload(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)
|
||||
{
|
||||
if (E.Owner.Reload())
|
||||
E.Origin.Tell("Sucessfully reloaded configs!");
|
||||
else
|
||||
E.Origin.Tell("Unable to reload configs :(");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,226 +8,20 @@ using System.Collections;
|
||||
|
||||
namespace IW4MAdmin
|
||||
{
|
||||
class Database
|
||||
abstract class Database
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
Clients,
|
||||
Stats
|
||||
}
|
||||
|
||||
public Database(String FN, Type T)
|
||||
public Database(String FN)
|
||||
{
|
||||
FileName = FN;
|
||||
DBCon = String.Format("Data Source={0}", FN);
|
||||
Con = new SQLiteConnection(DBCon);
|
||||
DBType = T;
|
||||
Init(T);
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init(Type T)
|
||||
{
|
||||
if(!File.Exists(FileName))
|
||||
{
|
||||
switch (T)
|
||||
{
|
||||
case Type.Clients:
|
||||
String query = "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);";
|
||||
ExecuteNonQuery(query);
|
||||
query = "CREATE TABLE [BANS] ( [Reason] TEXT NULL, [npID] TEXT NULL, [bannedByID] Text NULL);";
|
||||
ExecuteNonQuery(query);
|
||||
break;
|
||||
case Type.Stats:
|
||||
String query_stats = "CREATE TABLE [STATS] ( [Number] INTEGER, [KILLS] INTEGER DEFAULT 0, [DEATHS] INTEGER DEFAULT 0, [KDR] REAL DEFAULT 0, [SKILL] REAL DEFAULT 0 );";
|
||||
ExecuteNonQuery(query_stats);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"]);
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Player> findPlayers(String name)
|
||||
{
|
||||
String Query = String.Format("SELECT * FROM CLIENTS WHERE Name LIKE '%{0}%' LIMIT 10", name);
|
||||
DataTable Result = GetDataTable(Query);
|
||||
|
||||
List<Player> Players = new List<Player>();
|
||||
|
||||
if (Result != null && Result.Rows.Count > 0)
|
||||
{
|
||||
foreach (DataRow p in Result.Rows)
|
||||
{
|
||||
Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), ((int)p["Connections"])));
|
||||
}
|
||||
return Players;
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Player findPlayers(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)
|
||||
{
|
||||
foreach (DataRow p in Result.Rows)
|
||||
return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), ((int)p["Connections"]));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
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];
|
||||
return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), null, 0);
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Ban> getBans()
|
||||
{
|
||||
List<Ban> Bans = new List<Ban>();
|
||||
DataTable Result = GetDataTable("SELECT * FROM BANS");
|
||||
|
||||
foreach (DataRow Row in Result.Rows)
|
||||
Bans.Add(new Ban(Row["Reason"].ToString(), Row["npID"].ToString(), Row["bannedByID"].ToString()));
|
||||
|
||||
return Bans;
|
||||
}
|
||||
|
||||
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];
|
||||
return new Stats(Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["SKILL"]));
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeBan(String GUID)
|
||||
{
|
||||
String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}'", GUID);
|
||||
ExecuteNonQuery(Query);
|
||||
}
|
||||
|
||||
public void addPlayer(Player P)
|
||||
{
|
||||
Dictionary<String, object> newPlayer = new Dictionary<String, object>();
|
||||
|
||||
if (DBType == Type.Clients)
|
||||
{
|
||||
newPlayer.Add("Name", Utilities.removeNastyChars(P.getName()));
|
||||
newPlayer.Add("npID", P.getID());
|
||||
newPlayer.Add("Level", (int)P.getLevel());
|
||||
newPlayer.Add("LastOffense", "");
|
||||
newPlayer.Add("Connections", 1);
|
||||
|
||||
Insert("CLIENTS", newPlayer);
|
||||
}
|
||||
|
||||
if (DBType == Type.Stats)
|
||||
{
|
||||
newPlayer.Add("Number", P.getDBID());
|
||||
newPlayer.Add("KILLS", 0);
|
||||
newPlayer.Add("DEATHS", 0);
|
||||
newPlayer.Add("KDR", 0);
|
||||
newPlayer.Add("SKILL", 0);
|
||||
Insert("STATS", newPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Stats> topStats()
|
||||
{
|
||||
String Query = String.Format("SELECT * FROM STATS WHERE SKILL > '{0}' ORDER BY SKILL DESC LIMIT 4", 20);
|
||||
DataTable Result = GetDataTable(Query);
|
||||
|
||||
List<Stats> Top = new List<Stats>();
|
||||
|
||||
if (Result != null && Result.Rows.Count > 0)
|
||||
{
|
||||
foreach (DataRow D in Result.Rows)
|
||||
{
|
||||
Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]));
|
||||
if (S.Skill > 20)
|
||||
Top.Add(S);
|
||||
}
|
||||
}
|
||||
|
||||
return Top;
|
||||
}
|
||||
|
||||
public void updatePlayer(Player P)
|
||||
{
|
||||
Dictionary<String, object> updatedPlayer = new Dictionary<String, object>();
|
||||
|
||||
if (DBType == Type.Clients)
|
||||
{
|
||||
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());
|
||||
|
||||
Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.getID()));
|
||||
}
|
||||
|
||||
if (DBType == Type.Stats)
|
||||
{
|
||||
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);
|
||||
|
||||
Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.getDBID()));
|
||||
}
|
||||
}
|
||||
|
||||
public void addBan(Ban B)
|
||||
{
|
||||
Dictionary<String, object> newBan = new Dictionary<String, object>();
|
||||
|
||||
newBan.Add("Reason", B.getReason());
|
||||
newBan.Add("npID", B.getID());
|
||||
newBan.Add("bannedByID", B.getBanner());
|
||||
|
||||
Insert("BANS", newBan);
|
||||
}
|
||||
abstract public void Init();
|
||||
|
||||
//HELPERS
|
||||
|
||||
public bool Insert(String tableName, Dictionary<String, object> data)
|
||||
protected bool Insert(String tableName, Dictionary<String, object> data)
|
||||
{
|
||||
String columns = "";
|
||||
String values = "";
|
||||
@ -251,7 +45,7 @@ namespace IW4MAdmin
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public bool Update(String tableName, Dictionary<String, object> data, String where)
|
||||
protected bool Update(String tableName, Dictionary<String, object> data, String where)
|
||||
{
|
||||
String vals = "";
|
||||
Boolean returnCode = true;
|
||||
@ -275,13 +69,13 @@ namespace IW4MAdmin
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public DataRow getDataRow(String Q)
|
||||
protected DataRow getDataRow(String Q)
|
||||
{
|
||||
DataRow Result = GetDataTable(Q).Rows[0];
|
||||
return Result;
|
||||
}
|
||||
|
||||
private int ExecuteNonQuery(String Request)
|
||||
protected int ExecuteNonQuery(String Request)
|
||||
{
|
||||
Con.Open();
|
||||
SQLiteCommand CMD = new SQLiteCommand(Con);
|
||||
@ -291,7 +85,7 @@ namespace IW4MAdmin
|
||||
return rowsUpdated;
|
||||
}
|
||||
|
||||
public DataTable GetDataTable(String sql)
|
||||
protected DataTable GetDataTable(String sql)
|
||||
{
|
||||
DataTable dt = new DataTable();
|
||||
try
|
||||
@ -313,9 +107,328 @@ namespace IW4MAdmin
|
||||
}
|
||||
//END
|
||||
|
||||
private String FileName;
|
||||
private String DBCon;
|
||||
private SQLiteConnection Con;
|
||||
private Type DBType;
|
||||
protected String FileName;
|
||||
protected String DBCon;
|
||||
protected SQLiteConnection Con;
|
||||
}
|
||||
|
||||
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);";
|
||||
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];
|
||||
|
||||
|
||||
if (ResponseRow["IP"].ToString().Length < 2)
|
||||
ResponseRow["IP"] = DateTime.Now.ToString(); // because aliases and backwards compatibility
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if (p["IP"].ToString().Length < 2)
|
||||
p["IP"] = DateTime.Now.ToString(); // because aliases and backwards compatibility
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
//Returns a list of players matching name parameter, null if no players found matching
|
||||
public List<Player> findPlayers(String name)
|
||||
{
|
||||
String Query = String.Format("SELECT * FROM CLIENTS WHERE Name LIKE '%{0}%' LIMIT 8", name);
|
||||
DataTable Result = GetDataTable(Query);
|
||||
|
||||
List<Player> Players = new List<Player>();
|
||||
|
||||
if (Result != null && Result.Rows.Count > 0)
|
||||
{
|
||||
foreach (DataRow p in Result.Rows)
|
||||
{
|
||||
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()));
|
||||
}
|
||||
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<Ban> getBans()
|
||||
{
|
||||
List<Ban> Bans = new List<Ban>();
|
||||
DataTable Result = GetDataTable("SELECT * FROM BANS");
|
||||
|
||||
foreach (DataRow Row in Result.Rows)
|
||||
{
|
||||
if (Row["TIME"].ToString().Length < 2) //compatibility with my old database
|
||||
Row["TIME"] = DateTime.Now.ToString();
|
||||
if (Row["IP"].ToString().Length < 2)
|
||||
Row["IP"] = DateTime.Now.ToString(); //because we don't have old ip's and don't want a messy alias
|
||||
|
||||
Bans.Add(new Ban(Row["Reason"].ToString(), Row["npID"].ToString(), Row["bannedByID"].ToString(), DateTime.Parse(Row["TIME"].ToString()), Row["IP"].ToString()));
|
||||
}
|
||||
|
||||
return Bans;
|
||||
}
|
||||
|
||||
//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<String, object> newPlayer = new Dictionary<String, object>();
|
||||
|
||||
newPlayer.Add("Name", Utilities.removeNastyChars(P.getName()));
|
||||
newPlayer.Add("npID", P.getID());
|
||||
newPlayer.Add("Level", (int)P.getLevel());
|
||||
newPlayer.Add("LastOffense", "");
|
||||
newPlayer.Add("Connections", 1);
|
||||
newPlayer.Add("IP", P.getIP());
|
||||
|
||||
Insert("CLIENTS", newPlayer);
|
||||
}
|
||||
|
||||
///Update information of specified player
|
||||
public void updatePlayer(Player P)
|
||||
{
|
||||
Dictionary<String, Object> updatedPlayer = new Dictionary<String, Object>();
|
||||
|
||||
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());
|
||||
|
||||
Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.getID()));
|
||||
}
|
||||
|
||||
|
||||
//Add specified ban to database
|
||||
public void addBan(Ban B)
|
||||
{
|
||||
Dictionary<String, object> newBan = new Dictionary<String, object>();
|
||||
|
||||
newBan.Add("Reason", B.getReason());
|
||||
newBan.Add("npID", B.getID());
|
||||
newBan.Add("bannedByID", B.getBanner());
|
||||
newBan.Add("IP", B.getIP());
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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 );";
|
||||
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];
|
||||
return new Stats(Convert.ToInt32(ResponseRow["KILLS"]), Convert.ToInt32(ResponseRow["DEATHS"]), Convert.ToDouble(ResponseRow["KDR"]), Convert.ToDouble(ResponseRow["SKILL"]));
|
||||
}
|
||||
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addPlayer(Player P)
|
||||
{
|
||||
Dictionary<String, object> newPlayer = new Dictionary<String, object>();
|
||||
|
||||
newPlayer.Add("Number", P.getDBID());
|
||||
newPlayer.Add("KILLS", 0);
|
||||
newPlayer.Add("DEATHS", 0);
|
||||
newPlayer.Add("KDR", 0);
|
||||
newPlayer.Add("SKILL", 1);
|
||||
|
||||
Insert("STATS", newPlayer);
|
||||
}
|
||||
|
||||
//Update stat information of specified player
|
||||
public void updatePlayer(Player P)
|
||||
{
|
||||
Dictionary<String, object> updatedPlayer = new Dictionary<String, object>();
|
||||
|
||||
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);
|
||||
|
||||
Update("STATS", updatedPlayer, String.Format("Number = '{0}'", P.getDBID()));
|
||||
}
|
||||
|
||||
//Returns top 8 players (we filter through them later)
|
||||
public List<Stats> topStats()
|
||||
{
|
||||
String Query = String.Format("SELECT * FROM STATS WHERE SKILL > '{0}' ORDER BY SKILL DESC LIMIT 8", 20);
|
||||
DataTable Result = GetDataTable(Query);
|
||||
|
||||
List<Stats> Top = new List<Stats>();
|
||||
|
||||
if (Result != null && Result.Rows.Count > 0)
|
||||
{
|
||||
foreach (DataRow D in Result.Rows)
|
||||
{
|
||||
Stats S = new Stats(Convert.ToInt32(D["Number"]), Convert.ToInt32(D["DEATHS"]), Convert.ToDouble(D["KDR"]), Convert.ToDouble(D["SKILL"]));
|
||||
if (S.Skill > 20)
|
||||
Top.Add(S);
|
||||
}
|
||||
}
|
||||
|
||||
return Top;
|
||||
}
|
||||
|
||||
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<String, Object> () { {"SKILL", 1} }, String.Format("Number = '{0}'", D["Number"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 void addPlayer(Aliases Alias)
|
||||
{
|
||||
Dictionary<String, object> newPlayer = new Dictionary<String, object>();
|
||||
|
||||
newPlayer.Add("Number", Alias.getNumber());
|
||||
newPlayer.Add("NAMES", Alias.getNamesDB());
|
||||
newPlayer.Add("IPS", Alias.getIPSDB());
|
||||
|
||||
Insert("ALIASES", newPlayer);
|
||||
}
|
||||
|
||||
public void updatePlayer(Aliases Alias)
|
||||
{
|
||||
Dictionary<String, object> updatedPlayer = new Dictionary<String, object>();
|
||||
|
||||
updatedPlayer.Add("Number", Alias.getNumber());
|
||||
updatedPlayer.Add("NAMES", Alias.getNamesDB());
|
||||
updatedPlayer.Add("IPS", Alias.getIPSDB());
|
||||
|
||||
Update("ALIASES", updatedPlayer, String.Format("Number = '{0}'", Alias.getNumber()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace IW4MAdmin
|
||||
|
||||
public void Send()
|
||||
{
|
||||
String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.getClientNum().ToString() + '/' + Instance.getMaxClients().ToString());
|
||||
String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.getClientNum().ToString() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString());
|
||||
Handle.Request(URI);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
<PublisherName>RaidMax LLC</PublisherName>
|
||||
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
|
||||
<WebPage>publish.htm</WebPage>
|
||||
<ApplicationRevision>5</ApplicationRevision>
|
||||
<ApplicationRevision>6</ApplicationRevision>
|
||||
<ApplicationVersion>0.4.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
|
@ -10,7 +10,7 @@ namespace IW4MAdmin
|
||||
static String IP;
|
||||
static int Port;
|
||||
static String RCON;
|
||||
static public double Version = 0.4;
|
||||
static public double Version = 0.5;
|
||||
static public double latestVersion;
|
||||
|
||||
static void Main(string[] args)
|
||||
|
@ -21,8 +21,7 @@ namespace IW4MAdmin
|
||||
|
||||
public void updateSkill(double enemySkill)
|
||||
{
|
||||
Skill = (Math.Round((double)Kills * (((double)Kills / (double)Deaths) / 10), 2));
|
||||
Skill = Math.Round(Math.Log(Skill) * (enemySkill / 2) + (Math.Log(Deaths + 1) * 0.3) * 12, 2);
|
||||
Skill = Math.Round(Math.Log(KDR + 1) * ((enemySkill / 2) + 1) + (Math.Log(Deaths) * 0.3) * 12, 2);
|
||||
}
|
||||
|
||||
public int Kills;
|
||||
@ -31,6 +30,55 @@ namespace IW4MAdmin
|
||||
public double Skill;
|
||||
}
|
||||
|
||||
class Aliases
|
||||
{
|
||||
public Aliases(int Num, String N, String I)
|
||||
{
|
||||
Number = Num;
|
||||
Names = N;
|
||||
IPS = I;
|
||||
}
|
||||
|
||||
public List<String> getNames()
|
||||
{
|
||||
return new List<String>(Names.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
|
||||
public List<String> getIPS()
|
||||
{
|
||||
return new List<String>(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)
|
||||
{
|
||||
Names += Names + ';';
|
||||
}
|
||||
|
||||
public void addIP(String IP)
|
||||
{
|
||||
IPS += IP + ';';
|
||||
}
|
||||
|
||||
private String Names;
|
||||
private String IPS;
|
||||
private int Number;
|
||||
}
|
||||
|
||||
class Player
|
||||
{
|
||||
public enum Permission
|
||||
@ -55,7 +103,7 @@ namespace IW4MAdmin
|
||||
Warnings = 0;
|
||||
}
|
||||
|
||||
public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con)
|
||||
public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2)
|
||||
{
|
||||
Name = n;
|
||||
npID = id;
|
||||
@ -64,6 +112,7 @@ namespace IW4MAdmin
|
||||
dbID = cind;
|
||||
LastOffense = lo;
|
||||
Connections = con + 1;
|
||||
IP = IP2;
|
||||
Warnings = 0;
|
||||
}
|
||||
|
||||
@ -102,11 +151,21 @@ namespace IW4MAdmin
|
||||
return LastOffense;
|
||||
}
|
||||
|
||||
public String getIP()
|
||||
{
|
||||
return IP;
|
||||
}
|
||||
|
||||
public void updateName(String n)
|
||||
{
|
||||
Name = n;
|
||||
}
|
||||
|
||||
public void updateIP(String I)
|
||||
{
|
||||
IP = I;
|
||||
}
|
||||
|
||||
// BECAUSE IT NEEDS TO BE CHANGED!
|
||||
public void setLevel(Player.Permission Perm)
|
||||
{
|
||||
@ -158,10 +217,12 @@ namespace IW4MAdmin
|
||||
private Player.Permission Level;
|
||||
private int dbID;
|
||||
private int Connections;
|
||||
private String IP;
|
||||
|
||||
public Event lastEvent;
|
||||
public String LastOffense;
|
||||
public int Warnings;
|
||||
public Stats stats;
|
||||
public Aliases Alias;
|
||||
}
|
||||
}
|
||||
|
@ -22,52 +22,17 @@ namespace IW4MAdmin
|
||||
sv_connection.Client.SendTimeout = 1000;
|
||||
sv_connection.Client.ReceiveTimeout = 1000;
|
||||
Instance = I;
|
||||
toSend = new Queue<String>();
|
||||
toSend = new Queue<RCON_Request>();
|
||||
}
|
||||
|
||||
//When we don't care about a response
|
||||
public bool sendRCON(String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
String STR_REQUEST = String.Format("ÿÿÿÿrcon {0} {1}", Instance.getPassword(), message);
|
||||
|
||||
Byte[] Request_ = Encoding.Unicode.GetBytes(STR_REQUEST);
|
||||
Byte[] Request = new Byte[Request_.Length / 2];
|
||||
|
||||
int count = 0; //This is kinda hacky but Unicode -> ASCII doesn't seem to be working correctly for this.
|
||||
foreach (Byte b in Request_)
|
||||
{
|
||||
if (b != 0)
|
||||
Request[count / 2] = b;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
System.Net.IPAddress IP = System.Net.IPAddress.Parse(Instance.getIP());
|
||||
IPEndPoint endPoint = new IPEndPoint(IP, Instance.getPort());
|
||||
|
||||
sv_connection.Connect(endPoint);
|
||||
sv_connection.Send(Request, Request.Length);
|
||||
}
|
||||
|
||||
catch (SocketException)
|
||||
{
|
||||
Instance.Log.Write("Unable to reach server for sending RCON", Log.Level.Debug);
|
||||
sv_connection.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//We want to read the reponse
|
||||
public String[] responseSendRCON(String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
String STR_REQUEST;
|
||||
String STR_REQUEST = String.Empty;
|
||||
if (message != "getstatus")
|
||||
STR_REQUEST = String.Format("ÿÿÿÿrcon {0} {1}", Instance.getPassword().Replace("\r", String.Empty), message);
|
||||
STR_REQUEST = String.Format("ÿÿÿÿrcon {0} {1}", Instance.getPassword(), message);
|
||||
else
|
||||
STR_REQUEST = String.Format("ÿÿÿÿ getstatus");
|
||||
|
||||
@ -89,32 +54,49 @@ namespace IW4MAdmin
|
||||
sv_connection.Connect(endPoint);
|
||||
sv_connection.Send(Request, Request.Length);
|
||||
|
||||
String incoming = String.Empty;
|
||||
byte[] bufferRecv = new byte[65536];
|
||||
do
|
||||
{
|
||||
// loop on receiving the bytes
|
||||
bufferRecv = sv_connection.Receive(ref endPoint);
|
||||
|
||||
// only decode the bytes received
|
||||
incoming += (Encoding.ASCII.GetString(bufferRecv, 0, bufferRecv.Length));
|
||||
} while (sv_connection.Available > 0);
|
||||
|
||||
Byte[] receive = sv_connection.Receive(ref endPoint);
|
||||
int num = int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier);
|
||||
|
||||
String[] response = System.Text.Encoding.UTF8.GetString(receive).Split((char)num);
|
||||
String[] response = incoming.Split(new char[] {(char)num} , StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(response[1] == "Invalid password.")
|
||||
{
|
||||
Instance.Log.Write("Invalid RCON password specified", Log.Level.Debug);
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
catch (SocketException)
|
||||
{
|
||||
Instance.Log.Write("Unable to reach server for sending RCON", Log.Level.Debug);
|
||||
return null;
|
||||
}
|
||||
|
||||
catch (System.InvalidOperationException)
|
||||
{
|
||||
Instance.Log.Write("RCON Connection terminated by server. Uh-OH", Log.Level.Debug);
|
||||
sv_connection.Close();
|
||||
sv_connection = new UdpClient();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void addRCON(String Message, int delay)
|
||||
public String[] addRCON(String Message)
|
||||
{
|
||||
toSend.Enqueue(Message);
|
||||
RCON_Request newReq = new RCON_Request(Message);
|
||||
toSend.Enqueue(newReq);
|
||||
return newReq.waitForResponse();
|
||||
}
|
||||
|
||||
public void ManageRCONQueue()
|
||||
@ -123,7 +105,8 @@ namespace IW4MAdmin
|
||||
{
|
||||
if (toSend.Count > 0)
|
||||
{
|
||||
sendRCON(toSend.Peek());
|
||||
RCON_Request Current = toSend.Peek();
|
||||
Current.Response = responseSendRCON(Current.Request);
|
||||
toSend.Dequeue();
|
||||
Utilities.Wait(0.567);
|
||||
}
|
||||
@ -134,6 +117,31 @@ namespace IW4MAdmin
|
||||
|
||||
private UdpClient sv_connection;
|
||||
private Server Instance;
|
||||
private Queue<String> toSend;
|
||||
private Queue<RCON_Request> toSend;
|
||||
}
|
||||
|
||||
class RCON_Request
|
||||
{
|
||||
public RCON_Request(String IN)
|
||||
{
|
||||
Request = IN;
|
||||
Response = null;
|
||||
}
|
||||
|
||||
public String[] waitForResponse()
|
||||
{
|
||||
DateTime Start = DateTime.Now;
|
||||
DateTime Current = DateTime.Now;
|
||||
while (Response == null && (Current-Start).TotalMilliseconds < 1000)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
Current = DateTime.Now;
|
||||
}
|
||||
return Response;
|
||||
}
|
||||
|
||||
public String Request;
|
||||
public String[] Response;
|
||||
}
|
||||
|
||||
}
|
||||
|
336
Admin/Server.cs
336
Admin/Server.cs
@ -1,6 +1,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using System.Threading; //SLEEP
|
||||
using System.IO;
|
||||
@ -20,19 +21,23 @@ namespace IW4MAdmin
|
||||
clientnum = 0;
|
||||
RCON = new RCON(this);
|
||||
logFile = new file("admin_" + port + ".log", true);
|
||||
#if DEBUG
|
||||
Log = new Log(logFile, Log.Level.Debug);
|
||||
#else
|
||||
Log = new Log(logFile, Log.Level.Production);
|
||||
#endif
|
||||
players = new List<Player>(new Player[18]);
|
||||
DB = new Database("clients.rm", Database.Type.Clients);
|
||||
stats = new Database("stats_" + port + ".rm", Database.Type.Stats);
|
||||
Bans = DB.getBans();
|
||||
owner = DB.getOwner();
|
||||
maps = new List<Map>();
|
||||
rules = new List<String>();
|
||||
messages = new List<String>();
|
||||
clientDB = new ClientsDB("clients.rm");
|
||||
statDB = new StatsDB("stats_" + port + ".rm");
|
||||
aliasDB = new AliasesDB("aliases.rm");
|
||||
Bans = clientDB.getBans();
|
||||
owner = clientDB.getOwner();
|
||||
events = new Queue<Event>();
|
||||
HB = new Heartbeat(this);
|
||||
Macros = new Dictionary<String, Object>();
|
||||
nextMessage = 0;
|
||||
initCommands();
|
||||
initMacros();
|
||||
initMessages();
|
||||
initMaps();
|
||||
initRules();
|
||||
@ -100,41 +105,72 @@ namespace IW4MAdmin
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DB.getPlayer(P.getID(), P.getClientNum()) == null)
|
||||
DB.addPlayer(P);
|
||||
else
|
||||
if (clientDB.getPlayer(P.getID(), P.getClientNum()) == null)
|
||||
{
|
||||
clientDB.addPlayer(P);
|
||||
Player New = clientDB.getPlayer(P.getID(), P.getClientNum());
|
||||
statDB.addPlayer(New);
|
||||
aliasDB.addPlayer(new Aliases(New.getDBID(), New.getName(), New.getIP()));
|
||||
}
|
||||
|
||||
|
||||
//messy way to prevent loss of last event
|
||||
Player A;
|
||||
A = DB.getPlayer(P.getID(), P.getClientNum());
|
||||
if (A.getName() != P.getName())
|
||||
A.updateName(P.getName());
|
||||
A.lastEvent = P.lastEvent;
|
||||
P = A;
|
||||
}
|
||||
|
||||
P.stats = stats.getStats(P.getDBID());
|
||||
if (P.stats == null)
|
||||
Player NewPlayer = clientDB.getPlayer(P.getID(), P.getClientNum());
|
||||
NewPlayer.stats = statDB.getStats(NewPlayer.getDBID());
|
||||
if (NewPlayer.stats == null)
|
||||
{
|
||||
stats.addPlayer(P);
|
||||
P.stats = new Stats(0, 0, 0, 1);
|
||||
statDB.addPlayer(NewPlayer);
|
||||
NewPlayer.stats = statDB.getStats(NewPlayer.getDBID());
|
||||
}
|
||||
NewPlayer.Alias = aliasDB.getPlayer(NewPlayer.getDBID());
|
||||
NewPlayer.lastEvent = P.lastEvent;
|
||||
|
||||
if (players[NewPlayer.getClientNum()] == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
P.updateIP(IPS[P.getID()]);
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
Log.Write("Looks like the connecting player doesn't have an IP location assigned yet.", Log.Level.Debug);
|
||||
P.updateIP(getPlayerIP(P.getID()));
|
||||
}
|
||||
|
||||
if (P.getName() != NewPlayer.getName())
|
||||
{
|
||||
NewPlayer.updateName(P.getName());
|
||||
NewPlayer.Alias.addName(P.getName());
|
||||
}
|
||||
|
||||
if (P.getIP() != NewPlayer.getIP())
|
||||
{
|
||||
NewPlayer.updateIP(P.getIP());
|
||||
NewPlayer.Alias.addIP(P.getIP());
|
||||
}
|
||||
|
||||
if(players[P.getClientNum()] == null)
|
||||
clientnum++;
|
||||
}
|
||||
|
||||
players[P.getClientNum()] = null;
|
||||
players[P.getClientNum()] = P;
|
||||
NewPlayer.lastEvent = P.lastEvent;
|
||||
|
||||
if (P.getLevel() == Player.Permission.Banned)
|
||||
players[NewPlayer.getClientNum()] = null;
|
||||
players[NewPlayer.getClientNum()] = NewPlayer;
|
||||
|
||||
Ban B = isBanned(NewPlayer);
|
||||
if (NewPlayer.getLevel() == Player.Permission.Banned || B != null)
|
||||
{
|
||||
Log.Write("Banned client " + P.getName() + " trying to connect...", Log.Level.Debug);
|
||||
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + isBanned(P).getReason();
|
||||
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + B.getReason();
|
||||
P.Kick(Message);
|
||||
}
|
||||
|
||||
else
|
||||
Log.Write("Client " + P.getName() + " connecting...", Log.Level.Debug);
|
||||
Log.Write("Client " + NewPlayer.getName() + " connecting...", Log.Level.Debug);
|
||||
|
||||
clientDB.updatePlayer(NewPlayer);
|
||||
aliasDB.updatePlayer(NewPlayer.Alias);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -148,6 +184,8 @@ namespace IW4MAdmin
|
||||
//Remove player by CLIENT NUMBER
|
||||
public bool removePlayer(int cNum)
|
||||
{
|
||||
Log.Write("Updating stats for " + players[cNum].getName(), Log.Level.Debug);
|
||||
statDB.updatePlayer(players[cNum]);
|
||||
Log.Write("Client at " + cNum + " disconnecting...", Log.Level.Debug);
|
||||
players[cNum] = null;
|
||||
clientnum--;
|
||||
@ -196,19 +234,39 @@ namespace IW4MAdmin
|
||||
}
|
||||
|
||||
public Ban isBanned(Player C)
|
||||
{
|
||||
if (C.getLevel() == Player.Permission.Banned)
|
||||
{
|
||||
foreach (Ban B in Bans)
|
||||
{
|
||||
|
||||
if (B.getID() == C.getID())
|
||||
return B;
|
||||
}
|
||||
|
||||
if (B.getIP() == null)
|
||||
continue;
|
||||
|
||||
if (C.Alias.getIPS().Find(f => f.Contains(B.getIP())) != null)
|
||||
return B;
|
||||
|
||||
if (C.getIP() == B.getIP())
|
||||
return B;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPlayerIP(String GUID)
|
||||
{
|
||||
Dictionary<string, string> dict;
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
//because rcon can be weird
|
||||
dict = Utilities.IPFromStatus(RCON.addRCON("status"));
|
||||
count++;
|
||||
} while(dict.Count < clientnum || count < 5);
|
||||
return dict[GUID];
|
||||
}
|
||||
|
||||
public Command processCommand(Event E, Command C)
|
||||
{
|
||||
E.Data = Utilities.removeWords(E.Data, 1);
|
||||
@ -238,7 +296,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
int dbID = -1;
|
||||
int.TryParse(Args[0].Substring(1, Args[0].Length-1), out dbID);
|
||||
Player found = E.Owner.DB.findPlayers(dbID);
|
||||
Player found = E.Owner.clientDB.getPlayer(dbID);
|
||||
if (found != null)
|
||||
E.Target = found;
|
||||
}
|
||||
@ -282,6 +340,11 @@ namespace IW4MAdmin
|
||||
//Starts the monitoring process
|
||||
public void Monitor()
|
||||
{
|
||||
|
||||
//Handles new rcon requests in a fashionable manner
|
||||
Thread RCONQueue = new Thread(new ThreadStart(RCON.ManageRCONQueue));
|
||||
RCONQueue.Start();
|
||||
|
||||
if (!intializeBasics())
|
||||
{
|
||||
Log.Write("Stopping " + Port + " due to uncorrectable errors (check log)" + logPath, Log.Level.Production);
|
||||
@ -289,15 +352,11 @@ namespace IW4MAdmin
|
||||
return;
|
||||
}
|
||||
|
||||
//Handles new rcon requests in a fashionable manner
|
||||
Thread RCONQueue = new Thread(new ThreadStart(RCON.ManageRCONQueue));
|
||||
RCONQueue.Start();
|
||||
|
||||
//Handles new events in a fashionable manner
|
||||
Thread eventQueue = new Thread(new ThreadStart(manageEventQueue));
|
||||
eventQueue.Start();
|
||||
|
||||
int timeFailed = 0;
|
||||
int timesFailed = 0;
|
||||
long l_size = -1;
|
||||
String[] lines = new String[8];
|
||||
String[] oldLines = new String[8];
|
||||
@ -313,12 +372,23 @@ namespace IW4MAdmin
|
||||
lastMessage = DateTime.Now - start;
|
||||
if(lastMessage.TotalSeconds > messageTime && messages.Count > 0)
|
||||
{
|
||||
Broadcast(messages[nextMessage]);
|
||||
|
||||
if (RCON.responseSendRCON("sv_online") == null)
|
||||
{
|
||||
timesFailed++;
|
||||
Log.Write("Server appears to be offline - " + timesFailed, Log.Level.Debug);
|
||||
}
|
||||
else
|
||||
timesFailed = 0;
|
||||
Thread.Sleep(300);
|
||||
initMacros();
|
||||
Broadcast(Utilities.processMacro(Macros, messages[nextMessage]));
|
||||
if (nextMessage == (messages.Count - 1))
|
||||
nextMessage = 0;
|
||||
else
|
||||
nextMessage++;
|
||||
start = DateTime.Now;
|
||||
if (timesFailed <= 3)
|
||||
HB.Send();
|
||||
}
|
||||
|
||||
@ -387,7 +457,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] infoResponse = RCON.responseSendRCON("getstatus");
|
||||
String[] infoResponse = RCON.addRCON("getstatus");
|
||||
|
||||
if (infoResponse == null || infoResponse.Length < 2)
|
||||
{
|
||||
@ -396,32 +466,40 @@ namespace IW4MAdmin
|
||||
}
|
||||
|
||||
infoResponse = infoResponse[1].Split('\\');
|
||||
mapname = infoResponse[20];
|
||||
mapname = maps.Find(m => m.Name.Equals(mapname)).Alias;
|
||||
hostname = Utilities.stripColors(infoResponse[32]);
|
||||
IW_Ver = infoResponse[2];
|
||||
maxClients = Convert.ToInt32(infoResponse[6]);
|
||||
Gametype = infoResponse[8];
|
||||
Dictionary<String, String> infoResponseDict = new Dictionary<string, string>();
|
||||
|
||||
//get _Website
|
||||
String[] p = RCON.responseSendRCON("_Website");
|
||||
|
||||
if (p == null)
|
||||
for (int i = 0; i < infoResponse.Length; i++)
|
||||
{
|
||||
Log.Write("Could not website name!", Log.Level.All);
|
||||
return false;
|
||||
if (i%2 == 0 || infoResponse[i] == String.Empty)
|
||||
continue;
|
||||
infoResponseDict.Add(infoResponse[i], infoResponse[i+1]);
|
||||
}
|
||||
|
||||
p = p[1].Split('"');
|
||||
if (p[0].Trim() != "Unknown command")
|
||||
Website = (p[3].Substring(0, p[3].Length - 2).Trim());
|
||||
p = null;
|
||||
//END
|
||||
mapname = infoResponseDict["mapname"];
|
||||
try
|
||||
{
|
||||
mapname = maps.Find(m => m.Name.Equals(mapname)).Alias;
|
||||
}
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
catch(Exception)
|
||||
{
|
||||
Log.Write(mapname + " doesn't appear to be in the maps.cfg", Log.Level.Debug);
|
||||
}
|
||||
|
||||
//GET fs_basepath
|
||||
p = RCON.responseSendRCON("fs_basepath");
|
||||
hostname = Utilities.stripColors(infoResponseDict["sv_hostname"]);
|
||||
IW_Ver = infoResponseDict["shortversion"];
|
||||
maxClients = Convert.ToInt32(infoResponseDict["sv_maxclients"]);
|
||||
Gametype = infoResponseDict["g_gametype"];
|
||||
try
|
||||
{
|
||||
Website = infoResponseDict["_Website"];
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
Log.Write("Seems not to have website specified", Log.Level.Debug);
|
||||
}
|
||||
|
||||
String[] p =RCON.addRCON("fs_basepath");
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
@ -432,12 +510,10 @@ namespace IW4MAdmin
|
||||
p = p[1].Split('"');
|
||||
Basepath = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||
p = null;
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
//END
|
||||
|
||||
//get fs_game
|
||||
p = RCON.responseSendRCON("fs_game");
|
||||
p =RCON.addRCON("fs_game");
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
@ -449,11 +525,10 @@ namespace IW4MAdmin
|
||||
Mod = p[3].Substring(0, p[3].Length - 2).Trim().Replace('/', '\\');
|
||||
p = null;
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
//END
|
||||
|
||||
//get g_log
|
||||
p = RCON.responseSendRCON("g_log");
|
||||
p = RCON.addRCON("g_log");
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
@ -472,11 +547,10 @@ namespace IW4MAdmin
|
||||
string log = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||
p = null;
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
//END
|
||||
|
||||
//get g_logsync
|
||||
p = RCON.responseSendRCON("g_logsync");
|
||||
p =RCON.addRCON("g_logsync");
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
@ -489,15 +563,12 @@ namespace IW4MAdmin
|
||||
int logsync = Convert.ToInt32(p[3].Substring(0, p[3].Length - 2).Trim());
|
||||
p = null;
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
if (logsync != 1)
|
||||
RCON.sendRCON("g_logsync 1");
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
RCON.addRCON("g_logsync 1");
|
||||
//END
|
||||
|
||||
//get iw4m_onelog
|
||||
p = RCON.responseSendRCON("iw4m_onelog");
|
||||
p =RCON.addRCON("iw4m_onelog");
|
||||
|
||||
if (p[0] == String.Empty || p[1].Length < 15)
|
||||
{
|
||||
@ -510,8 +581,6 @@ namespace IW4MAdmin
|
||||
p = null;
|
||||
//END
|
||||
|
||||
Thread.Sleep(FLOOD_TIMEOUT);
|
||||
|
||||
if (Mod == String.Empty || onelog == "1")
|
||||
logPath = Basepath + '\\' + "m2demo" + '\\' + log;
|
||||
else
|
||||
@ -526,6 +595,24 @@ namespace IW4MAdmin
|
||||
logFile = new file(logPath);
|
||||
Log.Write("Log file is " + logPath, Log.Level.Debug);
|
||||
|
||||
//get players ip's
|
||||
p =RCON.addRCON("status");
|
||||
if (p == null)
|
||||
{
|
||||
Log.Write("Unable to get initial player list!", Log.Level.Debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
IPS = Utilities.IPFromStatus(p);
|
||||
|
||||
#if DEBUG
|
||||
/* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create("ftp://raidmax.org/logs/games_old.log");
|
||||
tmp.Credentials = new System.Net.NetworkCredential("*", "*");
|
||||
System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream();
|
||||
String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/
|
||||
logPath = "games_old.log";
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
@ -544,12 +631,11 @@ namespace IW4MAdmin
|
||||
return true;
|
||||
}
|
||||
|
||||
if (E.Type == Event.GType.Disconnect)
|
||||
if (E.Type == Event.GType.Disconnect && E.Origin.getClientNum() > 0)
|
||||
{
|
||||
if (getNumPlayers() > 0 && E.Origin != null)
|
||||
if (getNumPlayers() > 0 && E.Origin != null && players[E.Origin.getClientNum()] != null)
|
||||
{
|
||||
DB.updatePlayer(E.Origin);
|
||||
stats.updatePlayer(E.Origin);
|
||||
clientDB.updatePlayer(E.Origin);
|
||||
removePlayer(E.Origin.getClientNum());
|
||||
}
|
||||
return true;
|
||||
@ -565,7 +651,7 @@ namespace IW4MAdmin
|
||||
|
||||
E.Target.stats.Deaths++;
|
||||
E.Target.stats.updateKDR();
|
||||
E.Target.stats.updateSkill(E.Origin.stats.Skill);
|
||||
//E.Target.stats.updateSkill(E.Origin.stats.Skill);
|
||||
}
|
||||
}
|
||||
|
||||
@ -616,7 +702,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
if (P == null || P.stats == null)
|
||||
continue;
|
||||
stats.updatePlayer(P);
|
||||
statDB.updatePlayer(P);
|
||||
Log.Write("Updated stats for client " + P.getDBID(), Log.Level.Debug);
|
||||
}
|
||||
return true;
|
||||
@ -625,32 +711,54 @@ namespace IW4MAdmin
|
||||
return false;
|
||||
}
|
||||
|
||||
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<String>();
|
||||
maps = new List<Map>();
|
||||
rules = new List<String>();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//THESE MAY NEED TO BE MOVED
|
||||
public void Broadcast(String Message)
|
||||
{
|
||||
RCON.addRCON("sayraw " + Message, 0);
|
||||
RCON.addRCON("sayraw " + Message);
|
||||
}
|
||||
|
||||
public void Tell(String Message, Player Target)
|
||||
{
|
||||
RCON.addRCON("tell " + Target.getClientNum() + " " + Message + "^7", 0);
|
||||
RCON.addRCON("tell " + Target.getClientNum() + " " + Message + "^7");
|
||||
}
|
||||
|
||||
public void Kick(String Message, Player Target)
|
||||
{
|
||||
RCON.addRCON("clientkick " + Target.getClientNum() + " \"" + Message + "^7\"", 0);
|
||||
RCON.addRCON("clientkick " + Target.getClientNum() + " \"" + Message + "^7\"");
|
||||
}
|
||||
|
||||
public void Ban(String Message, Player Target, Player Origin)
|
||||
{
|
||||
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "^7\"", 0);
|
||||
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "^7\"");
|
||||
if (Origin != null)
|
||||
{
|
||||
Target.setLevel(Player.Permission.Banned);
|
||||
Ban newBan = new Ban(Target.getLastO(), Target.getID(), Origin.getID());
|
||||
Ban newBan = new Ban(Target.getLastO(), Target.getID(), Origin.getID(), DateTime.Now, Target.getIP());
|
||||
Bans.Add(newBan);
|
||||
DB.addBan(newBan);
|
||||
DB.updatePlayer(Target);
|
||||
clientDB.addBan(newBan);
|
||||
clientDB.updatePlayer(Target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,11 +768,11 @@ namespace IW4MAdmin
|
||||
{
|
||||
if (B.getID() == Target.getID())
|
||||
{
|
||||
DB.removeBan(GUID);
|
||||
clientDB.removeBan(GUID);
|
||||
Bans.Remove(B);
|
||||
Player P = DB.getPlayer(Target.getID(), 0);
|
||||
Player P = clientDB.getPlayer(Target.getID(), 0);
|
||||
P.setLevel(Player.Permission.User);
|
||||
DB.updatePlayer(P);
|
||||
clientDB.updatePlayer(P);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -675,29 +783,36 @@ namespace IW4MAdmin
|
||||
public void fastRestart(int delay)
|
||||
{
|
||||
Utilities.Wait(delay);
|
||||
RCON.addRCON("fast_restart", 0);
|
||||
RCON.addRCON("fast_restart");
|
||||
}
|
||||
|
||||
public void mapRotate(int delay)
|
||||
{
|
||||
Utilities.Wait(delay);
|
||||
RCON.addRCON("map_rotate", 0);
|
||||
RCON.addRCON("map_rotate");
|
||||
}
|
||||
|
||||
public void tempBan(String Message, Player Target)
|
||||
{
|
||||
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "\"", 0);
|
||||
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "\"");
|
||||
}
|
||||
|
||||
public void mapRotate()
|
||||
{
|
||||
RCON.addRCON("map_rotate", 0);
|
||||
RCON.addRCON("map_rotate");
|
||||
}
|
||||
|
||||
public void Map(String map)
|
||||
{
|
||||
RCON.addRCON("map " + map, 0);
|
||||
RCON.addRCON("map " + map);
|
||||
}
|
||||
|
||||
public String Wisdom()
|
||||
{
|
||||
String Quote = new Connection("http://www.iheartquotes.com/api/v1/random?max_lines=1&max_characters=200").Read();
|
||||
return Utilities.removeNastyChars(Quote);
|
||||
}
|
||||
|
||||
//END
|
||||
|
||||
//THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/
|
||||
@ -706,10 +821,20 @@ namespace IW4MAdmin
|
||||
return rcon_pass;
|
||||
}
|
||||
|
||||
private void initMacros()
|
||||
{
|
||||
Macros = new Dictionary<String, Object>();
|
||||
Macros.Add("WISDOM", Wisdom());
|
||||
Macros.Add("TOTALPLAYERS", clientDB.totalPlayers());
|
||||
}
|
||||
|
||||
private void initMaps()
|
||||
{
|
||||
maps = new List<Map>();
|
||||
|
||||
file mapfile = new file("config\\maps.cfg");
|
||||
String[] _maps = mapfile.readAll();
|
||||
mapfile.Close();
|
||||
if (_maps.Length > 2) // readAll returns minimum one empty string
|
||||
{
|
||||
foreach (String m in _maps)
|
||||
@ -728,8 +853,11 @@ namespace IW4MAdmin
|
||||
|
||||
private void initMessages()
|
||||
{
|
||||
messages = new List<String>();
|
||||
|
||||
file messageCFG = new file("config\\messages.cfg");
|
||||
String[] lines = messageCFG.readAll();
|
||||
messageCFG.Close();
|
||||
|
||||
if (lines.Length < 2) //readAll returns minimum one empty string
|
||||
{
|
||||
@ -756,8 +884,11 @@ namespace IW4MAdmin
|
||||
|
||||
private void initRules()
|
||||
{
|
||||
rules = new List<String>();
|
||||
|
||||
file ruleFile = new file("config\\rules.cfg");
|
||||
String[] _rules = ruleFile.readAll();
|
||||
ruleFile.Close();
|
||||
if (_rules.Length > 2) // readAll returns minimum one empty string
|
||||
{
|
||||
foreach (String r in _rules)
|
||||
@ -793,15 +924,16 @@ namespace IW4MAdmin
|
||||
commands.Add(new Uptime("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 <player> <reason>.", "w", Player.Permission.Moderator, 2, true));
|
||||
commands.Add(new WarnClear("warnclear", "remove all warning for a player syntax: !warnclear <player>.", "wc", Player.Permission.Administrator, 1, true));
|
||||
commands.Add(new Unban("unban", "unban player by guid. syntax: !unban <guid>.", "ub", Player.Permission.Administrator, 1, true));
|
||||
commands.Add(new Unban("unban", "unban player by guid. syntax: !unban <guid>.", "ub", Player.Permission.SeniorAdmin, 1, true));
|
||||
commands.Add(new Admins("admins", "list currently connected admins. syntax: !admins.", "a", Player.Permission.User, 0, false));
|
||||
commands.Add(new Wisdom("wisdom", "get a random wisdom quote. syntax: !wisdom", "w", Player.Permission.Administrator, 0, false));
|
||||
commands.Add(new MapCMD("map", "change to specified map. syntax: !map", "m", Player.Permission.Administrator, 1, false));
|
||||
commands.Add(new Find("find", "find player in database. syntax: !find <player>", "f", Player.Permission.Administrator, 1, false));
|
||||
commands.Add(new Find("find", "find player in database. syntax: !find <player>", "f", Player.Permission.SeniorAdmin, 1, false));
|
||||
commands.Add(new Rules("rules", "list server rules. syntax: !rules", "r", Player.Permission.User, 0, false));
|
||||
commands.Add(new PrivateMessage("privatemessage", "send message to other player. syntax: !pm <player> <message>", "pm", Player.Permission.User, 2, true));
|
||||
commands.Add(new _Stats("stats", "view your stats or another player's. syntax: !stats", "xlrstats", Player.Permission.User, 0, true));
|
||||
commands.Add(new TopStats("topstats", "view the top 4 players on this server. syntax !topstats", "xlrtopstats", Player.Permission.User, 0, false));
|
||||
commands.Add(new TopStats("topstats", "view the top 4 players on this server. syntax: !topstats", "xlrtopstats", Player.Permission.User, 0, false));
|
||||
commands.Add(new Reload("reload", "reload configurations. syntax: !reload", "reload", Player.Permission.Owner, 0, false));
|
||||
/*
|
||||
commands.Add(new commands { command = "stats", desc = "view your server stats.", requiredPer = 0 });
|
||||
commands.Add(new commands { command = "speed", desc = "change player speed. syntax: !speed <number>", requiredPer = 3 });
|
||||
@ -813,13 +945,14 @@ namespace IW4MAdmin
|
||||
//Objects
|
||||
public Log Log;
|
||||
public RCON RCON;
|
||||
public Database DB;
|
||||
public ClientsDB clientDB;
|
||||
public AliasesDB aliasDB;
|
||||
public StatsDB statDB;
|
||||
public List<Ban> Bans;
|
||||
public Player owner;
|
||||
public List<Map> maps;
|
||||
public List<String> rules;
|
||||
public Queue<Event> events;
|
||||
public Database stats;
|
||||
public Heartbeat HB;
|
||||
public String Website;
|
||||
public String Gametype;
|
||||
@ -840,6 +973,11 @@ namespace IW4MAdmin
|
||||
private int errors = 0;
|
||||
private String IW_Ver;
|
||||
private int maxClients;
|
||||
private Dictionary<String, Object> Macros;
|
||||
|
||||
|
||||
//Will probably move this later
|
||||
private Dictionary<String, String> IPS;
|
||||
|
||||
|
||||
//Log stuff
|
||||
|
@ -57,7 +57,7 @@ namespace IW4MAdmin
|
||||
|
||||
public static String removeNastyChars(String str)
|
||||
{
|
||||
return str.Replace("`", "").Replace("'", "").Replace("\\", "").Replace("\"", "").Replace("^", "").Replace(""", "''");
|
||||
return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace("^", "").Replace(""", "''").Replace("&", "&").Replace("\"", "''");
|
||||
}
|
||||
|
||||
public static int GetLineNumber(Exception ex)
|
||||
@ -86,17 +86,60 @@ namespace IW4MAdmin
|
||||
{
|
||||
case Player.Permission.Banned:
|
||||
return "^1" + Player.Permission.Banned;
|
||||
break;
|
||||
case Player.Permission.Owner:
|
||||
return "^5" + Player.Permission.Owner;
|
||||
break;
|
||||
case Player.Permission.User:
|
||||
return "^3" + Player.Permission.User;
|
||||
break;
|
||||
default:
|
||||
return "^2" + level;
|
||||
}
|
||||
}
|
||||
|
||||
public static String processMacro(Dictionary<String, Object> 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 Dictionary<String, String> IPFromStatus(String[] players)
|
||||
{
|
||||
Dictionary<String, String> Dict = new Dictionary<String, String>();
|
||||
|
||||
foreach (String S in players)
|
||||
{
|
||||
String S2 = S.Trim();
|
||||
if (S.Length < 50)
|
||||
continue;
|
||||
if (Regex.Matches(S2, @"\d+$", RegexOptions.IgnoreCase).Count > 0)
|
||||
{
|
||||
String[] eachPlayer = S2.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 3; i < eachPlayer.Length; i++ )
|
||||
{
|
||||
if (eachPlayer[i].Split(':').Length > 1)
|
||||
{
|
||||
Dict.Add(eachPlayer[3], eachPlayer[i].Split(':')[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return Dict;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
60
|
||||
This server uses ^5IW4M Admin v0.2 ^7get it at ^5raidmax.org
|
||||
This server uses ^5IW4M Admin v0.5 ^7get it at ^5raidmax.org
|
||||
^5IW4M Admin ^7sees ^5YOU!
|
||||
Cheaters are ^1unwelcome ^7 on this server
|
||||
Did you know 8/10 people agree with unverified statistics?
|
@ -1 +1,11 @@
|
||||
0.4
|
||||
VERSION: 0.5
|
||||
CHANGELOG:
|
||||
-close config files after reading oops
|
||||
-added reload command
|
||||
-added macros! (Denoted by {{MACRO}} in server config right now only {{WISDOM}} and {{TOTALPLAYERS}})
|
||||
-added IP's (tracks and rebans new accounts on same banned ip)!
|
||||
-aliases
|
||||
-reworked database classes
|
||||
-heartbeat gives running version
|
||||
-player banned in find gives last ban reason
|
||||
-reworked rcon yet again
|
||||
|
@ -1,22 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game_TEST", "Game_TEST\Game_TEST.csproj", "{119DA221-3EA7-432C-AAFC-782D94EA1ECF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{119DA221-3EA7-432C-AAFC-782D94EA1ECF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{119DA221-3EA7-432C-AAFC-782D94EA1ECF}.Debug|x86.Build.0 = Debug|x86
|
||||
{119DA221-3EA7-432C-AAFC-782D94EA1ECF}.Release|x86.ActiveCfg = Release|x86
|
||||
{119DA221-3EA7-432C-AAFC-782D94EA1ECF}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,91 +0,0 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Storage;
|
||||
using Microsoft.Xna.Framework.GamerServices;
|
||||
#endregion
|
||||
|
||||
namespace Game_TEST
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the main type for your game
|
||||
/// </summary>
|
||||
public class Game1 : Game
|
||||
{
|
||||
GraphicsDeviceManager graphics;
|
||||
SpriteBatch spriteBatch;
|
||||
|
||||
public Game1()
|
||||
: base()
|
||||
{
|
||||
graphics = new GraphicsDeviceManager(this);
|
||||
Content.RootDirectory = "Content";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to perform any initialization it needs to before starting to run.
|
||||
/// This is where it can query for any required services and load any non-graphic
|
||||
/// related content. Calling base.Initialize will enumerate through any components
|
||||
/// and initialize them as well.
|
||||
/// </summary>
|
||||
protected override void Initialize()
|
||||
{
|
||||
// TODO: Add your initialization logic here
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LoadContent will be called once per game and is the place to load
|
||||
/// all of your content.
|
||||
/// </summary>
|
||||
protected override void LoadContent()
|
||||
{
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
|
||||
// TODO: use this.Content to load your game content here
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnloadContent will be called once per game and is the place to unload
|
||||
/// all content.
|
||||
/// </summary>
|
||||
protected override void UnloadContent()
|
||||
{
|
||||
// TODO: Unload any non ContentManager content here
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to run logic such as updating the world,
|
||||
/// checking for collisions, gathering input, and playing audio.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||
Exit();
|
||||
|
||||
// TODO: Add your update logic here
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the game should draw itself.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
||||
protected override void Draw(GameTime gameTime)
|
||||
{
|
||||
GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||
|
||||
// TODO: Add your drawing code here
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{119DA221-3EA7-432C-AAFC-782D94EA1ECF}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Game_TEST</RootNamespace>
|
||||
<AssemblyName>Game_TEST</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Windows\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Windows\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Game1.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="MonoGame.Framework">
|
||||
<HintPath>$(MSBuildExtensionsPath)\..\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Content\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
Binary file not shown.
Before Width: | Height: | Size: 31 KiB |
@ -1,26 +0,0 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#endregion
|
||||
|
||||
namespace Game_TEST
|
||||
{
|
||||
#if WINDOWS || LINUX
|
||||
/// <summary>
|
||||
/// The main class.
|
||||
/// </summary>
|
||||
public static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
using (var game = new Game1())
|
||||
game.Run();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
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("Game_TEST")]
|
||||
[assembly: AssemblyProduct("Game_TEST")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 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("5c4ee4ad-a4b0-483e-a8e8-4cd17cfa4c2d")]
|
||||
|
||||
// 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")]
|
Loading…
Reference in New Issue
Block a user