Fixessss
preliminary trueskill testing
This commit is contained in:
parent
b0e32e9a91
commit
dad8fedc78
@ -15,6 +15,7 @@ namespace IW4MAdmin
|
|||||||
FileName = FN;
|
FileName = FN;
|
||||||
DBCon = String.Format("Data Source={0}", FN);
|
DBCon = String.Format("Data Source={0}", FN);
|
||||||
Con = new SQLiteConnection(DBCon);
|
Con = new SQLiteConnection(DBCon);
|
||||||
|
Open = false;
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where));
|
ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where));
|
||||||
}
|
}
|
||||||
catch (Exception fail)
|
catch (Exception fail)
|
||||||
{
|
{
|
||||||
@ -77,6 +78,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
protected int ExecuteNonQuery(String Request)
|
protected int ExecuteNonQuery(String Request)
|
||||||
{
|
{
|
||||||
|
waitForClose();
|
||||||
Con.Open();
|
Con.Open();
|
||||||
SQLiteCommand CMD = new SQLiteCommand(Con);
|
SQLiteCommand CMD = new SQLiteCommand(Con);
|
||||||
CMD.CommandText = Request;
|
CMD.CommandText = Request;
|
||||||
@ -90,6 +92,7 @@ namespace IW4MAdmin
|
|||||||
DataTable dt = new DataTable();
|
DataTable dt = new DataTable();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
waitForClose();
|
||||||
Con.Open();
|
Con.Open();
|
||||||
SQLiteCommand mycommand = new SQLiteCommand(Con);
|
SQLiteCommand mycommand = new SQLiteCommand(Con);
|
||||||
mycommand.CommandText = sql;
|
mycommand.CommandText = sql;
|
||||||
@ -105,11 +108,22 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void waitForClose()
|
||||||
|
{
|
||||||
|
while (Con.State == ConnectionState.Open)
|
||||||
|
{
|
||||||
|
Utilities.Wait(0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
//END
|
//END
|
||||||
|
|
||||||
protected String FileName;
|
protected String FileName;
|
||||||
protected String DBCon;
|
protected String DBCon;
|
||||||
protected SQLiteConnection Con;
|
protected SQLiteConnection Con;
|
||||||
|
protected bool Open;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientsDB : Database
|
class ClientsDB : Database
|
||||||
|
@ -69,10 +69,10 @@ namespace IW4MAdmin
|
|||||||
return new Event(GType.Connect, null, SV.clientFromLine(line, 3, true), null, SV);
|
return new Event(GType.Connect, null, SV.clientFromLine(line, 3, true), null, SV);
|
||||||
|
|
||||||
if (eventType == "Q")
|
if (eventType == "Q")
|
||||||
return new Event(GType.Disconnect, null, SV.clientFromLine(line, 3, false), null, null);
|
return new Event(GType.Disconnect, null, SV.getPlayers()[Convert.ToInt16(line[2])], null, null);
|
||||||
|
|
||||||
if (eventType == "K")
|
if (eventType == "K")
|
||||||
return new Event(GType.Kill, line[9], SV.clientFromLine(line[8]), SV.clientFromLine(line[4]), null);
|
return new Event(GType.Kill, line[9], SV.clientFromLineArr(line, true), SV.clientFromLineArr(line, false), null);
|
||||||
|
|
||||||
if (line[0].Substring(line[0].Length - 3).Trim() == "say")
|
if (line[0].Substring(line[0].Length - 3).Trim() == "say")
|
||||||
{
|
{
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="RCON.cs" />
|
<Compile Include="RCON.cs" />
|
||||||
<Compile Include="Server.cs" />
|
<Compile Include="Server.cs" />
|
||||||
|
<Compile Include="TrueSkill.cs" />
|
||||||
<Compile Include="Utilities.cs" />
|
<Compile Include="Utilities.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -12,6 +12,9 @@ namespace IW4MAdmin
|
|||||||
Deaths = D;
|
Deaths = D;
|
||||||
KDR = Math.Round(kdr,2);
|
KDR = Math.Round(kdr,2);
|
||||||
Skill = Math.Round(skill,2);
|
Skill = Math.Round(skill,2);
|
||||||
|
|
||||||
|
lastSigma = lastMew/3;
|
||||||
|
lastMew = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateKDR()
|
public void updateKDR()
|
||||||
@ -19,15 +22,18 @@ namespace IW4MAdmin
|
|||||||
KDR = Math.Round((double)((double)Kills / (double)Deaths), 2);
|
KDR = Math.Round((double)((double)Kills / (double)Deaths), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSkill(double enemySkill)
|
public void updateSkill()
|
||||||
{
|
{
|
||||||
Skill = Math.Round(Math.Log(KDR + 1) * ((enemySkill / 2) + 1) + (Math.Log(Deaths) * 0.3) * 12, 2);
|
Skill = TrueSkill.Gaussian(lastMew, lastSigma);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Kills;
|
public int Kills;
|
||||||
public int Deaths;
|
public int Deaths;
|
||||||
public double KDR;
|
public double KDR;
|
||||||
public double Skill;
|
public double Skill;
|
||||||
|
|
||||||
|
public double lastSigma;
|
||||||
|
public double lastMew;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Aliases
|
class Aliases
|
||||||
@ -98,7 +104,7 @@ namespace IW4MAdmin
|
|||||||
npID = id;
|
npID = id;
|
||||||
Number = num;
|
Number = num;
|
||||||
Level = (Player.Permission)l;
|
Level = (Player.Permission)l;
|
||||||
LastOffense = null;
|
LastOffense = String.Empty;
|
||||||
Connections = 0;
|
Connections = 0;
|
||||||
IP = "";
|
IP = "";
|
||||||
Warnings = 0;
|
Warnings = 0;
|
||||||
@ -113,8 +119,11 @@ namespace IW4MAdmin
|
|||||||
Number = num;
|
Number = num;
|
||||||
Level = l;
|
Level = l;
|
||||||
dbID = cind;
|
dbID = cind;
|
||||||
LastOffense = lo;
|
if (lo == null)
|
||||||
Connections = con + 1;
|
LastOffense = String.Empty;
|
||||||
|
else
|
||||||
|
LastOffense = lo;
|
||||||
|
Connections = con;
|
||||||
IP = IP2;
|
IP = IP2;
|
||||||
Warnings = 0;
|
Warnings = 0;
|
||||||
}
|
}
|
||||||
@ -219,7 +228,7 @@ namespace IW4MAdmin
|
|||||||
private int Number;
|
private int Number;
|
||||||
private Player.Permission Level;
|
private Player.Permission Level;
|
||||||
private int dbID;
|
private int dbID;
|
||||||
private int Connections;
|
public int Connections;
|
||||||
private String IP;
|
private String IP;
|
||||||
|
|
||||||
public Event lastEvent;
|
public Event lastEvent;
|
||||||
|
@ -99,6 +99,12 @@ namespace IW4MAdmin
|
|||||||
return newReq.waitForResponse();
|
return newReq.waitForResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
sv_connection.Close();
|
||||||
|
sv_connection = new UdpClient();
|
||||||
|
}
|
||||||
|
|
||||||
public void ManageRCONQueue()
|
public void ManageRCONQueue()
|
||||||
{
|
{
|
||||||
while (Instance.isRunning)
|
while (Instance.isRunning)
|
||||||
|
339
Admin/Server.cs
339
Admin/Server.cs
@ -100,65 +100,6 @@ namespace IW4MAdmin
|
|||||||
return Bans;
|
return Bans;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void threadedConnect(Player P, Player NewPlayer)
|
|
||||||
{
|
|
||||||
bool updated = false;
|
|
||||||
while (!updated)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
P.updateIP(IPS[P.getID()].Trim());
|
|
||||||
updated = true;
|
|
||||||
Log.Write("Sucessfully updated " + NewPlayer.getName() + "'s IP to " + P.getIP(), Log.Level.Debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//Log.Write("Looks like the connecting player doesn't have an IP location assigned yet. Let's wait for next poll", Log.Level.Debug);
|
|
||||||
Utilities.Wait(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NewPlayer.Alias == null)
|
|
||||||
{
|
|
||||||
aliasDB.addPlayer(new Aliases(NewPlayer.getDBID(), NewPlayer.getName(), P.getIP()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (P.getName() != NewPlayer.getName())
|
|
||||||
{
|
|
||||||
NewPlayer.updateName(P.getName());
|
|
||||||
NewPlayer.Alias.addName(P.getName());
|
|
||||||
aliasDB.updatePlayer(NewPlayer.Alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (P.getIP() != NewPlayer.getIP())
|
|
||||||
{
|
|
||||||
NewPlayer.updateIP(P.getIP());
|
|
||||||
NewPlayer.Alias.addIP(P.getIP());
|
|
||||||
aliasDB.updatePlayer(NewPlayer.Alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
clientDB.updatePlayer(NewPlayer);
|
|
||||||
|
|
||||||
Ban B = isBanned(NewPlayer);
|
|
||||||
if (B != null || NewPlayer.getLevel() == Player.Permission.Banned)
|
|
||||||
{
|
|
||||||
Log.Write("Banned client " + P.getName() + " trying to connect...", Log.Level.Debug);
|
|
||||||
string Reason = String.Empty;
|
|
||||||
if (B != null)
|
|
||||||
Reason = B.getReason();
|
|
||||||
else
|
|
||||||
Reason = P.LastOffense;
|
|
||||||
|
|
||||||
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + Reason;
|
|
||||||
P.Kick(Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
players[NewPlayer.getClientNum()] = null;
|
|
||||||
players[NewPlayer.getClientNum()] = NewPlayer;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add player object p to `players` list
|
//Add player object p to `players` list
|
||||||
public bool addPlayer(Player P)
|
public bool addPlayer(Player P)
|
||||||
{
|
{
|
||||||
@ -174,7 +115,6 @@ namespace IW4MAdmin
|
|||||||
aliasDB.addPlayer(new Aliases(New.getDBID(), New.getName(), New.getIP()));
|
aliasDB.addPlayer(new Aliases(New.getDBID(), New.getName(), New.getIP()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//messy way to prevent loss of last event
|
//messy way to prevent loss of last event
|
||||||
Player NewPlayer = clientDB.getPlayer(P.getID(), P.getClientNum());
|
Player NewPlayer = clientDB.getPlayer(P.getID(), P.getClientNum());
|
||||||
NewPlayer.stats = statDB.getStats(NewPlayer.getDBID());
|
NewPlayer.stats = statDB.getStats(NewPlayer.getDBID());
|
||||||
@ -193,8 +133,61 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
if (players[NewPlayer.getClientNum()] == null)
|
if (players[NewPlayer.getClientNum()] == null)
|
||||||
{
|
{
|
||||||
Thread connectThread = new Thread(() => threadedConnect(P, NewPlayer));
|
bool updated = false;
|
||||||
connectThread.Start(); // We don't want events to get behind
|
while (!updated)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
P.updateIP(IPS[P.getID()].Trim());
|
||||||
|
updated = true;
|
||||||
|
Log.Write("Sucessfully updated " + NewPlayer.getName() + "'s IP to " + P.getIP(), Log.Level.Debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Log.Write("Looks like the connecting player doesn't have an IP location assigned yet. Let's wait for next poll", Log.Level.Debug);
|
||||||
|
Utilities.Wait(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewPlayer.Alias == null)
|
||||||
|
{
|
||||||
|
aliasDB.addPlayer(new Aliases(NewPlayer.getDBID(), NewPlayer.getName(), P.getIP()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (P.getName() != NewPlayer.getName())
|
||||||
|
{
|
||||||
|
NewPlayer.updateName(P.getName());
|
||||||
|
NewPlayer.Alias.addName(P.getName());
|
||||||
|
aliasDB.updatePlayer(NewPlayer.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (P.getIP() != NewPlayer.getIP())
|
||||||
|
{
|
||||||
|
NewPlayer.updateIP(P.getIP());
|
||||||
|
NewPlayer.Alias.addIP(P.getIP());
|
||||||
|
aliasDB.updatePlayer(NewPlayer.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientDB.updatePlayer(NewPlayer);
|
||||||
|
NewPlayer.lastEvent.Owner = this; // cuz crashes
|
||||||
|
|
||||||
|
Ban B = isBanned(NewPlayer);
|
||||||
|
if (B != null || NewPlayer.getLevel() == Player.Permission.Banned)
|
||||||
|
{
|
||||||
|
Log.Write("Banned client " + P.getName() + " trying to connect...", Log.Level.Debug);
|
||||||
|
string Reason = String.Empty;
|
||||||
|
if (B != null)
|
||||||
|
Reason = B.getReason();
|
||||||
|
else
|
||||||
|
Reason = P.LastOffense;
|
||||||
|
|
||||||
|
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + Reason;
|
||||||
|
NewPlayer.Kick(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
players[NewPlayer.getClientNum()] = null;
|
||||||
|
players[NewPlayer.getClientNum()] = NewPlayer;
|
||||||
|
|
||||||
NewPlayer.Tell("Welcome ^5" + NewPlayer.getName() + " ^7this is your ^5" + Utilities.timesConnected(NewPlayer.getConnections()) + " ^7time connecting!");
|
NewPlayer.Tell("Welcome ^5" + NewPlayer.getName() + " ^7this is your ^5" + Utilities.timesConnected(NewPlayer.getConnections()) + " ^7time connecting!");
|
||||||
Log.Write("Client " + NewPlayer.getName() + " connecting...", Log.Level.Debug);
|
Log.Write("Client " + NewPlayer.getName() + " connecting...", Log.Level.Debug);
|
||||||
@ -215,12 +208,22 @@ namespace IW4MAdmin
|
|||||||
//Remove player by CLIENT NUMBER
|
//Remove player by CLIENT NUMBER
|
||||||
public bool removePlayer(int cNum)
|
public bool removePlayer(int cNum)
|
||||||
{
|
{
|
||||||
Log.Write("Updating stats for " + players[cNum].getName(), Log.Level.Debug);
|
if (cNum >= 0 && cNum < 18)
|
||||||
statDB.updatePlayer(players[cNum]);
|
{
|
||||||
Log.Write("Client at " + cNum + " disconnecting...", Log.Level.Debug);
|
Log.Write("Updating stats for " + players[cNum].getName(), Log.Level.Debug);
|
||||||
players[cNum] = null;
|
statDB.updatePlayer(players[cNum]);
|
||||||
clientnum--;
|
|
||||||
return true;
|
Log.Write("Client at " + cNum + " disconnecting...", Log.Level.Debug);
|
||||||
|
players[cNum] = null;
|
||||||
|
clientnum--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Write("Client disconnecting has an invalid client index!", Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get a client from players list by by log line. If create = true, it will return a new player object
|
//Get a client from players list by by log line. If create = true, it will return a new player object
|
||||||
@ -265,6 +268,58 @@ namespace IW4MAdmin
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Another version of client from line, written for the line created by a kill or death event
|
||||||
|
public Player clientFromLineArr(String[] L, bool kill)
|
||||||
|
{
|
||||||
|
if (L.Length < 7)
|
||||||
|
{
|
||||||
|
Log.Write("Line sent for client creation is not long enough!", Log.Level.Debug);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kill)
|
||||||
|
{
|
||||||
|
foreach (Player P in players)
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
if (P.getName().ToLower().Contains(L[8].Trim()))
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
String killerName = L[8].Trim();
|
||||||
|
String killerGUID = L[5].Trim();
|
||||||
|
int killerID = -1;
|
||||||
|
int.TryParse(L[6], out killerID);
|
||||||
|
Player newPlayer = new Player(killerName, killerGUID, killerID, 0);
|
||||||
|
|
||||||
|
addPlayer(newPlayer);
|
||||||
|
return players[newPlayer.getClientNum()];
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Player P in players)
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
if (P.getName().ToLower().Contains(L[4].Trim()))
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
String victimName = L[4].Trim();
|
||||||
|
String victimGUID = L[1].Trim();
|
||||||
|
int victimID = -1;
|
||||||
|
int.TryParse(L[2].Trim(), out victimID);
|
||||||
|
|
||||||
|
Player newPlayer = new Player(victimName, victimGUID, victimID, 0);
|
||||||
|
addPlayer(newPlayer);
|
||||||
|
return players[newPlayer.getClientNum()];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check ban list for every banned player and return ban if match is found
|
||||||
public Ban isBanned(Player C)
|
public Ban isBanned(Player C)
|
||||||
{
|
{
|
||||||
foreach (Ban B in Bans)
|
foreach (Ban B in Bans)
|
||||||
@ -286,19 +341,7 @@ namespace IW4MAdmin
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlayerIP(String GUID)
|
//Procses requested command correlating to an event
|
||||||
{
|
|
||||||
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)
|
public Command processCommand(Event E, Command C)
|
||||||
{
|
{
|
||||||
E.Data = Utilities.removeWords(E.Data, 1);
|
E.Data = Utilities.removeWords(E.Data, 1);
|
||||||
@ -324,16 +367,20 @@ namespace IW4MAdmin
|
|||||||
if (Args[0] == String.Empty)
|
if (Args[0] == String.Empty)
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
if (Args[0][0] == '@')
|
if (Args[0][0] == '@') // user specifying target by database ID
|
||||||
{
|
{
|
||||||
int dbID = -1;
|
int dbID = -1;
|
||||||
int.TryParse(Args[0].Substring(1, Args[0].Length-1), out dbID);
|
int.TryParse(Args[0].Substring(1, Args[0].Length-1), out dbID);
|
||||||
Player found = E.Owner.clientDB.getPlayer(dbID);
|
Player found = E.Owner.clientDB.getPlayer(dbID);
|
||||||
if (found != null)
|
if (found != null)
|
||||||
|
{
|
||||||
E.Target = found;
|
E.Target = found;
|
||||||
|
E.Target.lastEvent = E;
|
||||||
|
E.Owner = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(Args[0].Length < 3 && cNum > -1 && cNum < 18)
|
else if(Args[0].Length < 3 && cNum > -1 && cNum < 18) // user specifying target by client num
|
||||||
{
|
{
|
||||||
if (players[cNum] != null)
|
if (players[cNum] != null)
|
||||||
E.Target = players[cNum];
|
E.Target = players[cNum];
|
||||||
@ -351,11 +398,14 @@ namespace IW4MAdmin
|
|||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//push a new event into the queue
|
||||||
private void addEvent(Event E)
|
private void addEvent(Event E)
|
||||||
{
|
{
|
||||||
events.Enqueue(E);
|
events.Enqueue(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//process new event every 100 milliseconds
|
||||||
private void manageEventQueue()
|
private void manageEventQueue()
|
||||||
{
|
{
|
||||||
while (isRunning)
|
while (isRunning)
|
||||||
@ -385,7 +435,8 @@ namespace IW4MAdmin
|
|||||||
Utilities.Wait(10);
|
Utilities.Wait(10);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Thread to handle polling server for IP's
|
||||||
Thread statusUpdate = new Thread(new ThreadStart(pollServer));
|
Thread statusUpdate = new Thread(new ThreadStart(pollServer));
|
||||||
statusUpdate.Start();
|
statusUpdate.Start();
|
||||||
|
|
||||||
@ -414,15 +465,6 @@ namespace IW4MAdmin
|
|||||||
lastMessage = DateTime.Now - start;
|
lastMessage = DateTime.Now - start;
|
||||||
if(lastMessage.TotalSeconds > messageTime && messages.Count > 0)
|
if(lastMessage.TotalSeconds > messageTime && messages.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (RCON.addRCON("sv_online") == null)
|
|
||||||
{
|
|
||||||
timesFailed++;
|
|
||||||
Log.Write("Server appears to be offline - " + timesFailed, Log.Level.Debug);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
timesFailed = 0;
|
|
||||||
Thread.Sleep(300);
|
|
||||||
initMacros(); // somethings dynamically change so we have to re-init the dictionary
|
initMacros(); // somethings dynamically change so we have to re-init the dictionary
|
||||||
Broadcast(Utilities.processMacro(Macros, messages[nextMessage]));
|
Broadcast(Utilities.processMacro(Macros, messages[nextMessage]));
|
||||||
if (nextMessage == (messages.Count - 1))
|
if (nextMessage == (messages.Count - 1))
|
||||||
@ -508,17 +550,36 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
private void pollServer()
|
private void pollServer()
|
||||||
{
|
{
|
||||||
|
int timesFailed = 0;
|
||||||
while (isRunning)
|
while (isRunning)
|
||||||
{
|
{
|
||||||
IPS = Utilities.IPFromStatus(RCON.addRCON("status"));
|
IPS = Utilities.IPFromStatus(RCON.addRCON("status"));
|
||||||
while (IPS == null)
|
while (IPS == null)
|
||||||
{
|
{
|
||||||
|
timesFailed++;
|
||||||
|
Log.Write("Server appears to be offline - " + timesFailed, Log.Level.Debug);
|
||||||
|
|
||||||
|
if (timesFailed > 4)
|
||||||
|
{
|
||||||
|
Log.Write("Max offline attempts reached. Reinitializing RCON connection.", Log.Level.Debug);
|
||||||
|
RCON.Reset();
|
||||||
|
timesFailed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Write("Server responded to status query!", Log.Level.All);
|
||||||
|
timesFailed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
|
||||||
IPS = Utilities.IPFromStatus(RCON.addRCON("status"));
|
IPS = Utilities.IPFromStatus(RCON.addRCON("status"));
|
||||||
Utilities.Wait(1);
|
Utilities.Wait(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPoll = DateTime.Now;
|
lastPoll = DateTime.Now;
|
||||||
Utilities.Wait(15);
|
Utilities.Wait(20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,6 +621,7 @@ namespace IW4MAdmin
|
|||||||
IW_Ver = infoResponseDict["shortversion"];
|
IW_Ver = infoResponseDict["shortversion"];
|
||||||
maxClients = Convert.ToInt32(infoResponseDict["sv_maxclients"]);
|
maxClients = Convert.ToInt32(infoResponseDict["sv_maxclients"]);
|
||||||
Gametype = infoResponseDict["g_gametype"];
|
Gametype = infoResponseDict["g_gametype"];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Website = infoResponseDict["_Website"];
|
Website = infoResponseDict["_Website"];
|
||||||
@ -681,7 +743,7 @@ namespace IW4MAdmin
|
|||||||
tmp.Credentials = new System.Net.NetworkCredential("*", "*");
|
tmp.Credentials = new System.Net.NetworkCredential("*", "*");
|
||||||
System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream();
|
System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream();
|
||||||
String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/
|
String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/
|
||||||
logPath = "games_old.log";
|
//logPath = "games_old.log";
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -695,58 +757,113 @@ namespace IW4MAdmin
|
|||||||
//Process any server event
|
//Process any server event
|
||||||
public bool processEvent(Event E)
|
public bool processEvent(Event E)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
if (E.Type == Event.GType.Connect)
|
if (E.Type == Event.GType.Connect)
|
||||||
{
|
{
|
||||||
|
if (E.Origin == null)
|
||||||
|
Log.Write("Connect event triggered, but no client is detected!", Log.Level.Debug);
|
||||||
addPlayer(E.Origin);
|
addPlayer(E.Origin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Disconnect && E.Origin.getClientNum() > 0)
|
if (E.Type == Event.GType.Disconnect)
|
||||||
{
|
{
|
||||||
if (getNumPlayers() > 0 && E.Origin != null && players[E.Origin.getClientNum()] != null)
|
if (E.Origin == null)
|
||||||
{
|
{
|
||||||
clientDB.updatePlayer(E.Origin);
|
Log.Write("Disconnect event triggered, but no origin found.", Log.Level.Debug);
|
||||||
removePlayer(E.Origin.getClientNum());
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
E.Origin.Connections++;
|
||||||
|
clientDB.updatePlayer(E.Origin);
|
||||||
|
removePlayer(E.Origin.getClientNum());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Kill)
|
if (E.Type == Event.GType.Kill)
|
||||||
{
|
{
|
||||||
if (E.Origin != null && E.Target != null && E.Origin.stats != null)
|
if (E.Origin == null)
|
||||||
{
|
{
|
||||||
E.Origin.stats.Kills++;
|
Log.Write("Kill event triggered, but no origin found!", Log.Level.Debug);
|
||||||
E.Origin.stats.updateKDR();
|
return false;
|
||||||
E.Origin.stats.updateSkill(E.Target.stats.Skill);
|
|
||||||
|
|
||||||
E.Target.stats.Deaths++;
|
|
||||||
E.Target.stats.updateKDR();
|
|
||||||
//E.Target.stats.updateSkill(E.Origin.stats.Skill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (E.Target == null)
|
||||||
|
{
|
||||||
|
Log.Write("Kill event triggered, but no target found!", Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Origin.stats == null)
|
||||||
|
{
|
||||||
|
Log.Write("Kill event triggered, but no stats found for origin!", Log.Level.Debug);
|
||||||
|
E.Origin.stats = statDB.getStats(E.Origin.getDBID());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Target.stats == null)
|
||||||
|
{
|
||||||
|
Log.Write("Kill event triggered, but no stats found for target!", Log.Level.Debug);
|
||||||
|
E.Target.stats = statDB.getStats(E.Target.getDBID());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Write(E.Origin.getName() + " killed " + E.Target.getName() + " with a " + E.Data, Log.Level.Debug);
|
||||||
|
E.Origin.stats.Kills++;
|
||||||
|
E.Origin.stats.updateKDR();
|
||||||
|
|
||||||
|
E.Origin.stats.lastMew = TrueSkill.calculateWinnerMu(E.Origin.stats, E.Target.stats);
|
||||||
|
|
||||||
|
E.Origin.stats.lastSigma = TrueSkill.calculateWinnerSigma(E.Origin.stats, E.Target.stats);
|
||||||
|
E.Origin.stats.updateSkill();
|
||||||
|
|
||||||
|
E.Target.stats.Deaths++;
|
||||||
|
E.Target.stats.updateKDR();
|
||||||
|
|
||||||
|
E.Target.stats.lastMew = TrueSkill.calculateLoserMu(E.Target.stats, E.Origin.stats);
|
||||||
|
E.Target.stats.lastSigma = TrueSkill.calculateLoserSigma(E.Target.stats, E.Origin.stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Say && E.Origin != null)
|
if (E.Type == Event.GType.Say)
|
||||||
{
|
{
|
||||||
if (E.Data.Length < 2)
|
|
||||||
|
if (E.Data.Length < 2) // ITS A LIE!
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (E.Origin == null)
|
||||||
|
{
|
||||||
|
Log.Write("Say event triggered, but no origin found! - " + E.Data, Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Log.Write("Message from " + E.Origin.getName() + ": " + E.Data, Log.Level.Debug);
|
Log.Write("Message from " + E.Origin.getName() + ": " + E.Data, Log.Level.Debug);
|
||||||
|
|
||||||
if (E.Data.Substring(0, 1) != "!")
|
if (E.Owner == null)
|
||||||
|
{
|
||||||
|
Log.Write("Say event does not have an owner!", Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Data.Substring(0, 1) != "!") // Not a command so who gives an F?
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Command C = E.isValidCMD(commands);
|
Command C = E.isValidCMD(commands);
|
||||||
|
|
||||||
if (C != null)
|
if (C != null)
|
||||||
{
|
{
|
||||||
C = processCommand(E, C);
|
C = processCommand(E, C);
|
||||||
if (C != null)
|
if (C != null)
|
||||||
{
|
{
|
||||||
|
if (C.needsTarget() && E.Target == null)
|
||||||
|
{
|
||||||
|
Log.Write("Requested event requiring target does not have a target!", Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
C.Execute(E);
|
C.Execute(E);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Write("Error processing command by " + E.Origin.getName(), Log.Level.Debug);
|
Log.Write("Player didn't properly enter command - " + E.Origin.getName(), Log.Level.Debug);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
Admin/TrueSkill.cs
Normal file
55
Admin/TrueSkill.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class TrueSkill
|
||||||
|
{
|
||||||
|
public static double calculateWinnerMu(Stats originStats, Stats targetStats)
|
||||||
|
{
|
||||||
|
double Beta = originStats.lastMew / 6;
|
||||||
|
double lastSkill = Gaussian(originStats.lastMew, originStats.lastSigma);
|
||||||
|
double c = Math.Sqrt((2 * Beta * Beta) + (originStats.lastSigma * originStats.lastSigma) + (targetStats.lastSigma * targetStats.lastSigma));
|
||||||
|
double newMew = originStats.lastMew + ((originStats.lastSigma) * (originStats.lastSigma) / c) * ((originStats.lastMew - targetStats.lastMew) / c);
|
||||||
|
return newMew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double calculateLoserMu(Stats originStats, Stats targetStats)
|
||||||
|
{
|
||||||
|
double Beta = originStats.lastMew / 6;
|
||||||
|
double lastSkill = Gaussian(originStats.lastMew, originStats.lastSigma);
|
||||||
|
double c = Math.Sqrt( (2 * Beta * Beta) + (originStats.lastSigma * originStats.lastSigma) + (targetStats.lastSigma * targetStats.lastSigma));
|
||||||
|
double newMew = originStats.lastMew - ((targetStats.lastSigma) * (targetStats.lastSigma) / c) * ((originStats.lastMew - targetStats.lastMew) / c);
|
||||||
|
return newMew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double calculateLoserSigma(Stats originStats, Stats targetStats)
|
||||||
|
{
|
||||||
|
double Beta = originStats.lastMew / 6;
|
||||||
|
double lastSkill = Gaussian(originStats.lastMew, originStats.lastSigma);
|
||||||
|
double c = ((2 * Beta * Beta) + originStats.lastSigma * originStats.lastSigma) + (targetStats.lastSigma * targetStats.lastSigma);
|
||||||
|
double newSigma = originStats.lastSigma * ( 1 - (targetStats.lastSigma) * (targetStats.lastSigma) / c) * ((originStats.lastMew - targetStats.lastMew) / c);
|
||||||
|
return newSigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double calculateWinnerSigma(Stats originStats, Stats targetStats)
|
||||||
|
{
|
||||||
|
double Beta = originStats.lastMew / 6;
|
||||||
|
double lastSkill = Gaussian(originStats.lastMew, originStats.lastSigma);
|
||||||
|
double c = ((2 * Beta * Beta) + originStats.lastSigma * originStats.lastSigma) + (targetStats.lastSigma * targetStats.lastSigma);
|
||||||
|
double newSigma = originStats.lastSigma * (1 - (originStats.lastSigma) * (originStats.lastSigma) / c) * ((originStats.lastMew - targetStats.lastMew) / c);
|
||||||
|
return newSigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//https://gist.github.com/tansey/1444070
|
||||||
|
public static double Gaussian( double mean, double stddev)
|
||||||
|
{
|
||||||
|
|
||||||
|
double y1 = Math.Sqrt(-2.0 * Math.Log(.5)) * Math.Cos(2.0 * Math.PI * .5);
|
||||||
|
return y1 * stddev + mean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -148,7 +148,7 @@ namespace IW4MAdmin
|
|||||||
public static String timesConnected(int connection)
|
public static String timesConnected(int connection)
|
||||||
{
|
{
|
||||||
String Prefix = String.Empty;
|
String Prefix = String.Empty;
|
||||||
if (connection % 10 > 3 || connection % 10 == 0)
|
if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19))
|
||||||
Prefix = "th";
|
Prefix = "th";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user