update stats

change server id
fIx change log server complaining when empty read
This commit is contained in:
RaidMax 2018-11-27 18:31:48 -06:00
parent abf0609e2e
commit 9d6cbee69c
44 changed files with 966 additions and 157 deletions

View File

@ -8,7 +8,7 @@ namespace IW4MAdmin.Application.API.Master
public class ApiServer public class ApiServer
{ {
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public long Id { get; set; }
[JsonProperty("ip")] [JsonProperty("ip")]
public string IPAddress { get; set; } public string IPAddress { get; set; }
[JsonProperty("port")] [JsonProperty("port")]

View File

@ -43,7 +43,7 @@ namespace IW4MAdmin.Application.API.Master
Hostname = s.Hostname, Hostname = s.Hostname,
Map = s.CurrentMap.Name, Map = s.CurrentMap.Name,
MaxClientNum = s.MaxClients, MaxClientNum = s.MaxClients,
Id = s.GetHashCode(), Id = s.EndPoint,
Port = (short)s.GetPort(), Port = (short)s.GetPort(),
IPAddress = s.IP IPAddress = s.IP
}).ToList() }).ToList()

View File

@ -50,7 +50,7 @@ namespace IW4MAdmin.Application.IO
catch (Exception e) catch (Exception e)
{ {
Server.Logger.WriteWarning($"Failed to update log event for {Server.GetHashCode()}"); Server.Logger.WriteWarning($"Failed to update log event for {Server.EndPoint}");
Server.Logger.WriteDebug($"Exception: {e.Message}"); Server.Logger.WriteDebug($"Exception: {e.Message}");
Server.Logger.WriteDebug($"StackTrace: {e.StackTrace}"); Server.Logger.WriteDebug($"StackTrace: {e.StackTrace}");
} }

View File

@ -30,32 +30,32 @@ namespace IW4MAdmin
{ {
} }
public override int GetHashCode() //public override int EndPoint
{ //{
// hack: my laziness // // hack: my laziness
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28965") // if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28965")
{ // {
return 886229536; // return 886229536;
} // }
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28960") // if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28960")
{ // {
return 1645744423; // return 1645744423;
} // }
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28970") // if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28970")
{ // {
return 1645809959; // return 1645809959;
} // }
if (Id == 0) // if (Id == 0)
{ // {
Id = HashCode.Combine(IP, Port); // Id = HashCode.Combine(IP, Port);
Id = Id < 0 ? Math.Abs(Id) : Id; // Id = Id < 0 ? Math.Abs(Id) : Id;
} // }
return Id; // return Id;
} //}
override public async Task OnClientConnected(EFClient clientFromLog) override public async Task OnClientConnected(EFClient clientFromLog)
{ {
@ -763,7 +763,7 @@ namespace IW4MAdmin
this.MaxClients = maxplayers; this.MaxClients = maxplayers;
this.FSGame = game; this.FSGame = game;
this.Gametype = gametype; this.Gametype = gametype;
this.IP = ip.Value; this.IP = ip.Value == "localhost" ? ServerConfig.IPAddress : ip.Value;
if (logsync.Value == 0 || logfile.Value == string.Empty) if (logsync.Value == 0 || logfile.Value == string.Empty)
{ {

View File

@ -46,7 +46,7 @@ namespace IW4MAdmin.Application
ManualResetEventSlim OnQuit; ManualResetEventSlim OnQuit;
readonly IPageList PageList; readonly IPageList PageList;
readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim(1, 1); readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim(1, 1);
readonly Dictionary<int, ILogger> Loggers = new Dictionary<int, ILogger>(); readonly Dictionary<long, ILogger> Loggers = new Dictionary<long, ILogger>();
private ApplicationManager() private ApplicationManager()
{ {
@ -143,7 +143,7 @@ namespace IW4MAdmin.Application
public async Task UpdateServerStates() public async Task UpdateServerStates()
{ {
// store the server hash code and task for it // store the server hash code and task for it
var runningUpdateTasks = new Dictionary<int, Task>(); var runningUpdateTasks = new Dictionary<long, Task>();
while (Running) while (Running)
{ {
@ -163,16 +163,16 @@ namespace IW4MAdmin.Application
} }
// remove the update tasks as they have completd // remove the update tasks as they have completd
foreach (int serverId in serverTasksToRemove) foreach (long serverId in serverTasksToRemove)
{ {
runningUpdateTasks.Remove(serverId); runningUpdateTasks.Remove(serverId);
} }
// select the servers where the tasks have completed // select the servers where the tasks have completed
var serverIds = Servers.Select(s => s.GetHashCode()).Except(runningUpdateTasks.Select(r => r.Key)).ToList(); var serverIds = Servers.Select(s => s.EndPoint).Except(runningUpdateTasks.Select(r => r.Key)).ToList();
foreach (var server in Servers.Where(s => serverIds.Contains(s.GetHashCode()))) foreach (var server in Servers.Where(s => serverIds.Contains(s.EndPoint)))
{ {
runningUpdateTasks.Add(server.GetHashCode(), Task.Run(async () => runningUpdateTasks.Add(server.EndPoint, Task.Run(async () =>
{ {
try try
{ {
@ -467,7 +467,7 @@ namespace IW4MAdmin.Application
Running = false; Running = false;
} }
public ILogger GetLogger(int serverId) public ILogger GetLogger(long serverId)
{ {
if (Loggers.ContainsKey(serverId)) if (Loggers.ContainsKey(serverId))
{ {

View File

@ -48,8 +48,8 @@
<Folder Include="GameLogServer\" /> <Folder Include="GameLogServer\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="FolderProfile.pubxml" />
<Content Include="requirements.txt" /> <Content Include="requirements.txt" />
<None Include="Stable.pubxml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Interpreter Include="env\"> <Interpreter Include="env\">

View File

@ -5,26 +5,27 @@ import time
class LogReader(object): class LogReader(object):
def __init__(self): def __init__(self):
self.log_file_sizes = {} self.log_file_sizes = {}
# (if the file changes more than this, ignore ) - 1 MB # (if the file changes more than this, ignore ) - 0.125 MB
self.max_file_size_change = 1000000 self.max_file_size_change = 125000
# (if the time between checks is greater, ignore ) - 5 minutes # (if the time between checks is greater, ignore ) - 5 minutes
self.max_file_time_change = 1000 self.max_file_time_change = 60
def read_file(self, path): def read_file(self, path):
# prevent traversing directories # prevent traversing directories
if re.search('r^.+\.\.\\.+$', path): if re.search('r^.+\.\.\\.+$', path):
return False return False
# must be a valid log path and log file # must be a valid log path and log file
if not re.search(r'^.+[\\|\/](userraw|mods)[\\|\/].+.log$', path): if not re.search(r'^.+[\\|\/](userraw|mods|main)[\\|\/].+.log$', path):
return False return False
# set the initialze size to the current file size # set the initialze size to the current file size
file_size = 0 file_size = 0
if path not in self.log_file_sizes: if path not in self.log_file_sizes:
self.log_file_sizes[path] = { self.log_file_sizes[path] = {
'length' : self.file_length(path), 'length' : self.file_length(path),
'read': time.time() 'read': time.time()
} }
return '' return True
# grab the previous values # grab the previous values
last_length = self.log_file_sizes[path]['length'] last_length = self.log_file_sizes[path]['length']
@ -50,8 +51,8 @@ class LogReader(object):
# if it's been too long since we read and the amount changed is too great, discard it # if it's been too long since we read and the amount changed is too great, discard it
# todo: do we really want old events? maybe make this an "or" # todo: do we really want old events? maybe make this an "or"
if file_size_difference > self.max_file_size_change and time_difference > self.max_file_time_change: if file_size_difference > self.max_file_size_change or time_difference > self.max_file_time_change:
return '' return True
new_log_info = self.get_file_lines(path, file_size_difference) new_log_info = self.get_file_lines(path, file_size_difference)
return new_log_info return new_log_info

View File

@ -10,8 +10,10 @@ class LogResource(Resource):
if log_info is False: if log_info is False:
print('could not read log file ' + path) print('could not read log file ' + path)
empty_read = (log_info == False) or (log_info == True)
return { return {
'success' : log_info is not False, 'success' : log_info is not False,
'length': -1 if log_info is False else len(log_info), 'length': -1 if empty_read else len(log_info),
'data': log_info 'data': log_info
} }

View File

@ -1,12 +1,26 @@
Flask==1.0.2
aniso8601==3.0.2 aniso8601==3.0.2
APScheduler==3.5.3
certifi==2018.10.15
chardet==3.0.4
click==6.7 click==6.7
Flask==1.0.2
Flask-JWT==0.3.2
Flask-JWT-Extended==3.8.1
Flask-RESTful==0.3.6 Flask-RESTful==0.3.6
idna==2.7
itsdangerous==0.24 itsdangerous==0.24
Jinja2==2.10 Jinja2==2.10
MarkupSafe==1.0 MarkupSafe==1.0
marshmallow==3.0.0b8
pip==9.0.3 pip==9.0.3
pytz==2018.5 psutil==5.4.8
setuptools==39.0.1 pygal==2.4.0
PyJWT==1.4.2
pytz==2018.7
requests==2.20.0
setuptools==40.5.0
six==1.11.0 six==1.11.0
timeago==1.0.8
tzlocal==1.5.1
urllib3==1.24
Werkzeug==0.14.1 Werkzeug==0.14.1

View File

@ -12,4 +12,4 @@ if __name__ == '__main__':
except ValueError: except ValueError:
PORT = 5555 PORT = 5555
init() init()
app.run(HOST, PORT, debug=True) app.run(HOST, PORT, debug=False)

View File

@ -4,7 +4,7 @@ from master.models.servermodel import ServerModel
class ServerSchema(Schema): class ServerSchema(Schema):
id = fields.Int( id = fields.Int(
required=True, required=True,
validate=validate.Range(1, 2147483647, 'invalid id') validate=validate.Range(1, 25525525525565535, 'invalid id')
) )
ip = fields.Str( ip = fields.Str(
required=True required=True

View File

@ -26,7 +26,7 @@ namespace IW4ScriptCommands.Commands
{ {
CurrentTeam = (IW4MAdmin.Plugins.Stats.IW4Info.Team)Enum.Parse(typeof(IW4MAdmin.Plugins.Stats.IW4Info.Team), c[1]), CurrentTeam = (IW4MAdmin.Plugins.Stats.IW4Info.Team)Enum.Parse(typeof(IW4MAdmin.Plugins.Stats.IW4Info.Team), c[1]),
Num = server.GetClientsAsList().FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0]))?.ClientNumber ?? -1, Num = server.GetClientsAsList().FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0]))?.ClientNumber ?? -1,
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(server.Clients.FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0])).ClientId, server.GetHashCode()) Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(server.Clients.FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0])).ClientId, server.EndPoint)
}) })
.ToList(); .ToList();
@ -49,8 +49,8 @@ namespace IW4ScriptCommands.Commands
var activeClients = _c.Select(c => new TeamAssignment() var activeClients = _c.Select(c => new TeamAssignment()
{ {
Num = c.ClientNumber, Num = c.ClientNumber,
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.GetHashCode()), Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.EndPoint),
CurrentTeam = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.GetHashCode()).Team CurrentTeam = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.EndPoint).Team
}) })
.Where(c => scriptClientTeams.FirstOrDefault(sc => sc.Num == c.Num)?.CurrentTeam != IW4MAdmin.Plugins.Stats.IW4Info.Team.Spectator) .Where(c => scriptClientTeams.FirstOrDefault(sc => sc.Num == c.Num)?.CurrentTeam != IW4MAdmin.Plugins.Stats.IW4Info.Team.Spectator)
.Where(c => c.CurrentTeam != scriptClientTeams.FirstOrDefault(p => p.Num == c.Num)?.CurrentTeam) .Where(c => c.CurrentTeam != scriptClientTeams.FirstOrDefault(p => p.Num == c.Num)?.CurrentTeam)

View File

@ -42,7 +42,7 @@ namespace WebfrontCore.Controllers.API
var client = Manager.GetActiveClients() var client = Manager.GetActiveClients()
.FirstOrDefault(c => c.NetworkId == networkId.ConvertLong()); .FirstOrDefault(c => c.NetworkId == networkId.ConvertLong());
var server = Manager.GetServers().First(c => c.GetHashCode() == serverId); var server = Manager.GetServers().First(c => c.EndPoint == serverId);
teams = teams ?? string.Empty; teams = teams ?? string.Empty;

View File

@ -19,7 +19,7 @@ namespace IW4ScriptCommands
{ {
if (E.Type == GameEvent.EventType.Start) if (E.Type == GameEvent.EventType.Start)
{ {
return S.SetDvarAsync("sv_iw4madmin_serverid", S.GetHashCode()); return S.SetDvarAsync("sv_iw4madmin_serverid", S.EndPoint);
} }
if (E.Type == GameEvent.EventType.Warn) if (E.Type == GameEvent.EventType.Warn)

View File

@ -9,6 +9,7 @@ using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Database; using SharedLibraryCore.Database;
using System.Collections.Generic; using System.Collections.Generic;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using IW4MAdmin.Plugins.Stats.Helpers;
namespace IW4MAdmin.Plugins.Stats.Commands namespace IW4MAdmin.Plugins.Stats.Commands
{ {
@ -16,7 +17,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands
{ {
public static async Task<List<string>> GetMostPlayed(Server s) public static async Task<List<string>> GetMostPlayed(Server s)
{ {
int serverId = s.GetHashCode(); long serverId = await StatManager.GetIdForServer(s);
List<string> mostPlayed = new List<string>() List<string> mostPlayed = new List<string>()
{ {
$"^5--{Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTPLAYED_TEXT"]}--" $"^5--{Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTPLAYED_TEXT"]}--"

View File

@ -1,14 +1,10 @@
using SharedLibraryCore; using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Objects;
using IW4MAdmin.Plugins.Stats.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharedLibraryCore.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SharedLibraryCore;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using System.Linq;
using System.Threading.Tasks;
namespace IW4MAdmin.Plugins.Stats.Commands namespace IW4MAdmin.Plugins.Stats.Commands
{ {
@ -21,13 +17,14 @@ namespace IW4MAdmin.Plugins.Stats.Commands
if (E.Origin.ClientNumber >= 0) if (E.Origin.ClientNumber >= 0)
{ {
int serverId = E.Owner.GetHashCode(); long serverId = await Helpers.StatManager.GetIdForServer(E.Owner);
EFClientStatistics clientStats; EFClientStatistics clientStats;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
clientStats = await ctx.Set<EFClientStatistics>() clientStats = await ctx.Set<EFClientStatistics>()
.Where(s => s.ClientId == E.Origin.ClientId && s.ServerId == serverId) .Where(s => s.ClientId == E.Origin.ClientId)
.Where(s => s.ServerId == serverId)
.FirstAsync(); .FirstAsync();
clientStats.Deaths = 0; clientStats.Deaths = 0;
@ -39,7 +36,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
clientStats.EloRating = 200.0; clientStats.EloRating = 200.0;
// reset the cached version // reset the cached version
Plugin.Manager.ResetStats(E.Origin.ClientId, E.Owner.GetHashCode()); Plugin.Manager.ResetStats(E.Origin.ClientId, serverId);
// fixme: this doesn't work properly when another context exists // fixme: this doesn't work properly when another context exists
await ctx.SaveChangesAsync(); await ctx.SaveChangesAsync();

View File

@ -10,6 +10,7 @@ using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Database; using SharedLibraryCore.Database;
using System.Collections.Generic; using System.Collections.Generic;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using IW4MAdmin.Plugins.Stats.Helpers;
namespace IW4MAdmin.Plugins.Stats.Commands namespace IW4MAdmin.Plugins.Stats.Commands
{ {
@ -17,7 +18,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
{ {
public static async Task<List<string>> GetTopStats(Server s) public static async Task<List<string>> GetTopStats(Server s)
{ {
int serverId = s.GetHashCode(); long serverId = await StatManager.GetIdForServer(s);
List<string> topStatsText = new List<string>() List<string> topStatsText = new List<string>()
{ {
$"^5--{Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--" $"^5--{Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--"

View File

@ -43,7 +43,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
} }
} }
int serverId = E.Owner.GetHashCode(); long serverId = await StatManager.GetIdForServer(E.Owner);
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {

View File

@ -21,7 +21,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{ {
public class StatManager public class StatManager
{ {
private ConcurrentDictionary<int, ServerStats> Servers; private ConcurrentDictionary<long, ServerStats> Servers;
private ILogger Log; private ILogger Log;
private readonly IManager Manager; private readonly IManager Manager;
@ -30,19 +30,19 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public StatManager(IManager mgr) public StatManager(IManager mgr)
{ {
Servers = new ConcurrentDictionary<int, ServerStats>(); Servers = new ConcurrentDictionary<long, ServerStats>();
Log = mgr.GetLogger(0); Log = mgr.GetLogger(0);
Manager = mgr; Manager = mgr;
OnProcessingPenalty = new SemaphoreSlim(1, 1); OnProcessingPenalty = new SemaphoreSlim(1, 1);
OnProcessingSensitive = new SemaphoreSlim(1, 1); OnProcessingSensitive = new SemaphoreSlim(1, 1);
} }
public EFClientStatistics GetClientStats(int clientId, int serverId) public EFClientStatistics GetClientStats(int clientId, long serverId)
{ {
return Servers[serverId].PlayerStats[clientId]; return Servers[serverId].PlayerStats[clientId];
} }
public static Expression<Func<EFRating, bool>> GetRankingFunc(int? serverId = null) public static Expression<Func<EFRating, bool>> GetRankingFunc(long? serverId = null)
{ {
var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15); var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15);
return (r) => r.ServerId == serverId && return (r) => r.ServerId == serverId &&
@ -191,21 +191,36 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// insert the server if it does not exist // insert the server if it does not exist
try try
{ {
int serverId = sv.GetHashCode(); long serverId = GetIdForServer(sv).Result;
EFServer server; EFServer server;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
var serverSet = ctx.Set<EFServer>(); var serverSet = ctx.Set<EFServer>();
// get the server from the database if it exists, otherwise create and insert a new one // get the server from the database if it exists, otherwise create and insert a new one
server = serverSet.FirstOrDefault(c => c.ServerId == serverId); server = serverSet.FirstOrDefault(s => s.ServerId == serverId);
// the server might be using legacy server id
if (server == null)
{
server = serverSet.FirstOrDefault(s => s.EndPoint == sv.ToString());
if (server != null)
{
// this provides a way to identify legacy server entries
server.EndPoint = sv.ToString();
ctx.Update(server);
ctx.SaveChanges();
}
}
// server has never been added before
if (server == null) if (server == null)
{ {
server = new EFServer() server = new EFServer()
{ {
Port = sv.GetPort(), Port = sv.GetPort(),
Active = true, EndPoint = sv.ToString(),
ServerId = serverId ServerId = serverId
}; };
@ -216,7 +231,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
// check to see if the stats have ever been initialized // check to see if the stats have ever been initialized
var serverStats = InitializeServerStats(sv); var serverStats = InitializeServerStats(server.ServerId);
Servers.TryAdd(serverId, new ServerStats(server, serverStats) Servers.TryAdd(serverId, new ServerStats(server, serverStats)
{ {
@ -227,6 +242,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (Exception e) catch (Exception e)
{ {
Log.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]} - {e.Message}"); Log.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]} - {e.Message}");
Log.WriteDebug(e.GetExceptionInfo());
} }
} }
@ -241,7 +257,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
try try
{ {
int serverId = pl.CurrentServer.GetHashCode(); long serverId = await GetIdForServer(pl.CurrentServer);
if (!Servers.ContainsKey(serverId)) if (!Servers.ContainsKey(serverId))
{ {
@ -298,7 +314,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{ {
Log.WriteWarning("Adding new client to stats failed"); Log.WriteWarning("Adding new client to stats failed");
} }
} }
else else
@ -374,19 +389,19 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// <returns></returns> /// <returns></returns>
public async Task RemovePlayer(EFClient pl) public async Task RemovePlayer(EFClient pl)
{ {
Log.WriteInfo($"Removing {pl} from stats"); pl.CurrentServer.Logger.WriteInfo($"Removing {pl} from stats");
int serverId = pl.CurrentServer.GetHashCode(); long serverId = await GetIdForServer(pl.CurrentServer);
var playerStats = Servers[serverId].PlayerStats; var playerStats = Servers[serverId].PlayerStats;
var detectionStats = Servers[serverId].PlayerDetections; var detectionStats = Servers[serverId].PlayerDetections;
var serverStats = Servers[serverId].ServerStatistics; var serverStats = Servers[serverId].ServerStatistics;
if (!playerStats.ContainsKey(pl.ClientId)) if (!playerStats.ContainsKey(pl.ClientId))
{ {
Log.WriteWarning($"Client disconnecting not in stats {pl}"); pl.CurrentServer.Logger.WriteWarning($"Client disconnecting not in stats {pl}");
// remove the client from the stats dictionary as they're leaving // remove the client from the stats dictionary as they're leaving
playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue1); playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue1);
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue2); detectionStats.TryRemove(pl.ClientId, out Detection removedValue2);
return; return;
} }
@ -395,7 +410,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// remove the client from the stats dictionary as they're leaving // remove the client from the stats dictionary as they're leaving
playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue3); playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue3);
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue4); detectionStats.TryRemove(pl.ClientId, out Detection removedValue4);
// sync their stats before they leave // sync their stats before they leave
clientStats = UpdateStats(clientStats); clientStats = UpdateStats(clientStats);
@ -407,10 +422,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
// increment the total play time // increment the total play time
serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds; serverStats.TotalPlayTime += pl.ConnectionLength;
} }
public void AddDamageEvent(string eventLine, int attackerClientId, int victimClientId, int serverId) public void AddDamageEvent(string eventLine, int attackerClientId, int victimClientId, long serverId)
{ {
string regex = @"^(D);(.+);([0-9]+);(allies|axis);(.+);([0-9]+);(allies|axis);(.+);(.+);([0-9]+);(.+);(.+)$"; string regex = @"^(D);(.+);([0-9]+);(allies|axis);(.+);([0-9]+);(allies|axis);(.+);(.+);([0-9]+);(.+);(.+)$";
var match = Regex.Match(eventLine, regex, RegexOptions.IgnoreCase); var match = Regex.Match(eventLine, regex, RegexOptions.IgnoreCase);
@ -431,7 +446,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// Process stats for kill event /// Process stats for kill event
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task AddScriptHit(bool isDamage, DateTime time, EFClient attacker, EFClient victim, int serverId, string map, string hitLoc, string type, public async Task AddScriptHit(bool isDamage, DateTime time, EFClient attacker, EFClient victim, long serverId, string map, string hitLoc, string type,
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads,
string fraction, string visibilityPercentage, string snapAngles) string fraction, string visibilityPercentage, string snapAngles)
{ {
@ -581,7 +596,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
} }
void ApplyPenalty(Cheat.DetectionPenaltyResult penalty, Cheat.Detection clientDetection, EFClient attacker, DatabaseContext ctx) void ApplyPenalty(DetectionPenaltyResult penalty, Detection clientDetection, EFClient attacker, DatabaseContext ctx)
{ {
switch (penalty.ClientPenalty) switch (penalty.ClientPenalty)
{ {
@ -693,7 +708,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public async Task AddStandardKill(EFClient attacker, EFClient victim) public async Task AddStandardKill(EFClient attacker, EFClient victim)
{ {
int serverId = attacker.CurrentServer.GetHashCode(); long serverId = await GetIdForServer(attacker.CurrentServer);
EFClientStatistics attackerStats = null; EFClientStatistics attackerStats = null;
if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId)) if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
@ -723,6 +738,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// update the total stats // update the total stats
Servers[serverId].ServerStatistics.TotalKills += 1; Servers[serverId].ServerStatistics.TotalKills += 1;
await Sync(attacker.CurrentServer);
// this happens when the round has changed // this happens when the round has changed
if (attackerStats.SessionScore == 0) if (attackerStats.SessionScore == 0)
@ -997,6 +1013,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// calulate elo // calulate elo
if (Servers[attackerStats.ServerId].PlayerStats.Count > 1) if (Servers[attackerStats.ServerId].PlayerStats.Count > 1)
{ {
#region DEPRECATED
/* var validAttackerLobbyRatings = Servers[attackerStats.ServerId].PlayerStats /* var validAttackerLobbyRatings = Servers[attackerStats.ServerId].PlayerStats
.Where(cs => cs.Value.ClientId != attackerStats.ClientId) .Where(cs => cs.Value.ClientId != attackerStats.ClientId)
.Where(cs => .Where(cs =>
@ -1020,6 +1037,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
double victimLobbyRating = validVictimLobbyRatings.Count() > 0 ? double victimLobbyRating = validVictimLobbyRatings.Count() > 0 ?
validVictimLobbyRatings.Average(cs => cs.Value.EloRating) : validVictimLobbyRatings.Average(cs => cs.Value.EloRating) :
victimStats.EloRating;*/ victimStats.EloRating;*/
#endregion
double attackerEloDifference = Math.Log(Math.Max(1, victimStats.EloRating)) - Math.Log(Math.Max(1, attackerStats.EloRating)); double attackerEloDifference = Math.Log(Math.Max(1, victimStats.EloRating)) - Math.Log(Math.Max(1, attackerStats.EloRating));
double winPercentage = 1.0 / (1 + Math.Pow(10, attackerEloDifference / Math.E)); double winPercentage = 1.0 / (1 + Math.Pow(10, attackerEloDifference / Math.E));
@ -1122,9 +1140,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
return clientStats; return clientStats;
} }
public EFServerStatistics InitializeServerStats(Server sv) public EFServerStatistics InitializeServerStats(long serverId)
{ {
int serverId = sv.GetHashCode();
EFServerStatistics serverStats; EFServerStatistics serverStats;
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
@ -1134,7 +1151,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (serverStats == null) if (serverStats == null)
{ {
Log.WriteDebug($"Initializing server stats for {sv}"); Log.WriteDebug($"Initializing server stats for {serverId}");
// server stats have never been generated before // server stats have never been generated before
serverStats = new EFServerStatistics() serverStats = new EFServerStatistics()
{ {
@ -1151,7 +1168,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
return serverStats; return serverStats;
} }
public void ResetKillstreaks(int serverId) public void ResetKillstreaks(long serverId)
{ {
var serverStats = Servers[serverId]; var serverStats = Servers[serverId];
@ -1161,7 +1178,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
} }
public void ResetStats(int clientId, int serverId) public void ResetStats(int clientId, long serverId)
{ {
var stats = Servers[serverId].PlayerStats[clientId]; var stats = Servers[serverId].PlayerStats[clientId];
stats.Kills = 0; stats.Kills = 0;
@ -1172,7 +1189,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
stats.EloRating = 200; stats.EloRating = 200;
} }
public async Task AddMessageAsync(int clientId, int serverId, string message) public async Task AddMessageAsync(int clientId, long serverId, string message)
{ {
// the web users can have no account // the web users can have no account
if (clientId < 1) if (clientId < 1)
@ -1196,19 +1213,64 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public async Task Sync(Server sv) public async Task Sync(Server sv)
{ {
int serverId = sv.GetHashCode(); long serverId = await GetIdForServer(sv);
using (var ctx = new DatabaseContext(disableTracking: true)) using (var ctx = new DatabaseContext(disableTracking: true))
{ {
var serverSet = ctx.Set<EFServer>(); var serverSet = ctx.Set<EFServer>();
serverSet.Update(Servers[serverId].Server); serverSet.Update(Servers[serverId].Server);
var serverStatsSet = ctx.Set<EFServerStatistics>();
serverStatsSet.Update(Servers[serverId].ServerStatistics);
await ctx.SaveChangesAsync(); await ctx.SaveChangesAsync();
} }
} }
public void SetTeamBased(int serverId, bool isTeamBased) public void SetTeamBased(long serverId, bool isTeamBased)
{ {
Servers[serverId].IsTeamBased = isTeamBased; Servers[serverId].IsTeamBased = isTeamBased;
} }
public static async Task<long> GetIdForServer(Server server)
{
// hack: my laziness
if ($"{server.IP}:{server.GetPort().ToString()}" == "66.150.121.184:28965")
{
return 886229536;
}
else if ($"{server.IP}:{server.GetPort().ToString()}" == "66.150.121.184:28960")
{
return 1645744423;
}
else if ($"{server.IP}:{server.GetPort().ToString()}" == "66.150.121.184:28970")
{
return 1645809959;
}
else
{
long id = HashCode.Combine(server.IP, server.GetPort());
id = id < 0 ? Math.Abs(id) : id;
long? serverId;
// todo: cache this eventually, as it shouldn't change
using (var ctx = new DatabaseContext(disableTracking: true))
{
serverId = (await ctx.Set<EFServer>().FirstOrDefaultAsync(_server => _server.ServerId == server.EndPoint ||
_server.EndPoint == server.ToString() ||
_server.ServerId == id))?.ServerId;
}
if (!serverId.HasValue)
{
return id;
}
return serverId.Value;
}
}
} }
} }

View File

@ -18,7 +18,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
public int AttackerId { get; set; } public int AttackerId { get; set; }
[ForeignKey("AttackerId")] [ForeignKey("AttackerId")]
public virtual EFClient Attacker { get; set; } public virtual EFClient Attacker { get; set; }
public int ServerId { get; set; } public long ServerId { get; set; }
[ForeignKey("ServerId")] [ForeignKey("ServerId")]
public virtual EFServer Server { get; set; } public virtual EFServer Server { get; set; }
public IW4Info.HitLocation HitLoc { get; set; } public IW4Info.HitLocation HitLoc { get; set; }

View File

@ -13,7 +13,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
{ {
[Key] [Key]
public long MessageId { get; set; } public long MessageId { get; set; }
public int ServerId { get; set; } public long ServerId { get; set; }
[ForeignKey("ServerId")] [ForeignKey("ServerId")]
public virtual EFServer Server { get; set; } public virtual EFServer Server { get; set; }
public int ClientId { get; set; } public int ClientId { get; set; }

View File

@ -15,7 +15,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
public int ClientId { get; set; } public int ClientId { get; set; }
[ForeignKey("ClientId")] [ForeignKey("ClientId")]
public virtual EFClient Client { get; set; } public virtual EFClient Client { get; set; }
public int ServerId { get; set; } public long ServerId { get; set; }
[ForeignKey("ServerId")] [ForeignKey("ServerId")]
public virtual EFServer Server { get; set; } public virtual EFServer Server { get; set; }
[Required] [Required]

View File

@ -20,7 +20,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
public int ClientId { get; set; } public int ClientId { get; set; }
[ForeignKey("ClientId"), Column(Order = 0 )] [ForeignKey("ClientId"), Column(Order = 0 )]
public EFClient Client { get; set; } public EFClient Client { get; set; }
public int ServerId { get; set; } public long ServerId { get; set; }
[ForeignKey("ServerId"), Column(Order = 1)] [ForeignKey("ServerId"), Column(Order = 1)]
public EFServer Server { get; set; } public EFServer Server { get; set; }
} }

View File

@ -13,7 +13,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
[ForeignKey("RatingHistoryId")] [ForeignKey("RatingHistoryId")]
public virtual EFClientRatingHistory RatingHistory { get; set; } public virtual EFClientRatingHistory RatingHistory { get; set; }
// if null, indicates that the rating is an average rating // if null, indicates that the rating is an average rating
public int? ServerId { get; set; } public long? ServerId { get; set; }
// [ForeignKey("ServerId")] can't make this nullable if this annotation is set // [ForeignKey("ServerId")] can't make this nullable if this annotation is set
public virtual EFServer Server { get; set; } public virtual EFServer Server { get; set; }
[Required] [Required]

View File

@ -9,8 +9,9 @@ namespace IW4MAdmin.Plugins.Stats.Models
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)] [DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ServerId { get; set; } public long ServerId { get; set; }
[Required] [Required]
public int Port { get; set; } public int Port { get; set; }
public string EndPoint { get; set; }
} }
} }

View File

@ -8,7 +8,7 @@ namespace IW4MAdmin.Plugins.Stats.Models
{ {
[Key] [Key]
public int StatisticId { get; set; } public int StatisticId { get; set; }
public int ServerId { get; set; } public long ServerId { get; set; }
[ForeignKey("ServerId")] [ForeignKey("ServerId")]
public virtual EFServer Server { get; set; } public virtual EFServer Server { get; set; }
public long TotalKills { get; set; } public long TotalKills { get; set; }

View File

@ -1,7 +1,6 @@
using Microsoft.EntityFrameworkCore; using IW4MAdmin.Plugins.Stats.Models;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using IW4MAdmin.Plugins.Stats.Models;
namespace Stats.Models namespace Stats.Models
{ {

View File

@ -1,20 +1,19 @@
using System; using IW4MAdmin.Plugins.Stats.Config;
using System.Collections.Generic; using IW4MAdmin.Plugins.Stats.Helpers;
using System.Linq; using IW4MAdmin.Plugins.Stats.Models;
using System.Threading.Tasks; using Microsoft.EntityFrameworkCore;
using System.Reflection;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
using SharedLibraryCore.Helpers; using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Services; using SharedLibraryCore.Services;
using IW4MAdmin.Plugins.Stats.Config; using System;
using IW4MAdmin.Plugins.Stats.Helpers; using System.Collections.Generic;
using IW4MAdmin.Plugins.Stats.Models; using System.Linq;
using SharedLibraryCore.Database; using System.Reflection;
using Microsoft.EntityFrameworkCore; using System.Threading.Tasks;
namespace IW4MAdmin.Plugins.Stats namespace IW4MAdmin.Plugins.Stats
{ {
@ -44,16 +43,19 @@ namespace IW4MAdmin.Plugins.Stats
break; break;
case GameEvent.EventType.Disconnect: case GameEvent.EventType.Disconnect:
await Manager.RemovePlayer(E.Origin); await Manager.RemovePlayer(E.Origin);
await Manager.Sync(S);
break; break;
case GameEvent.EventType.Say: case GameEvent.EventType.Say:
if (!string.IsNullOrEmpty(E.Data) && if (!string.IsNullOrEmpty(E.Data) &&
E.Origin.ClientId > 1) E.Origin.ClientId > 1)
await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data); {
await Manager.AddMessageAsync(E.Origin.ClientId, await StatManager.GetIdForServer(E.Owner), E.Data);
}
break; break;
case GameEvent.EventType.MapChange: case GameEvent.EventType.MapChange:
Manager.SetTeamBased(E.Owner.GetHashCode(), E.Owner.Gametype != "dm"); Manager.SetTeamBased(await StatManager.GetIdForServer(E.Owner), E.Owner.Gametype != "dm");
Manager.ResetKillstreaks(S.GetHashCode()); Manager.ResetKillstreaks(await StatManager.GetIdForServer(E.Owner));
await Manager.Sync(S);
break; break;
case GameEvent.EventType.MapEnd: case GameEvent.EventType.MapEnd:
break; break;
@ -77,7 +79,7 @@ namespace IW4MAdmin.Plugins.Stats
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
if (killInfo.Length >= 14) if (killInfo.Length >= 14)
{ {
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8], await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]); killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
} }
break; break;
@ -90,14 +92,14 @@ namespace IW4MAdmin.Plugins.Stats
case GameEvent.EventType.Damage: case GameEvent.EventType.Damage:
if (!E.Owner.CustomCallback) if (!E.Owner.CustomCallback)
{ {
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, E.Owner.GetHashCode()); Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, await StatManager.GetIdForServer(E.Owner));
} }
break; break;
case GameEvent.EventType.ScriptDamage: case GameEvent.EventType.ScriptDamage:
killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
if (killInfo.Length >= 14) if (killInfo.Length >= 14)
{ {
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8], await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]); killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
} }
break; break;
@ -327,12 +329,17 @@ namespace IW4MAdmin.Plugins.Stats
Manager = new StatManager(manager); Manager = new StatManager(manager);
} }
public Task OnTickAsync(Server S) => Task.CompletedTask; public Task OnTickAsync(Server S)
{
return Task.CompletedTask;
}
public async Task OnUnloadAsync() public async Task OnUnloadAsync()
{ {
foreach (var sv in ServerManager.GetServers()) foreach (var sv in ServerManager.GetServers())
{
await Manager.Sync(sv); await Manager.Sync(sv);
} }
} }
} }
}

View File

@ -9,7 +9,7 @@ namespace SharedLibraryCore.Dtos
/// </summary> /// </summary>
public class EntityInfo public class EntityInfo
{ {
public int Id { get; set; } public long Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
} }
} }

View File

@ -17,7 +17,7 @@ namespace SharedLibraryCore.Dtos
public List<ChatInfo> ChatHistory { get; set; } public List<ChatInfo> ChatHistory { get; set; }
public List<PlayerInfo> Players { get; set; } public List<PlayerInfo> Players { get; set; }
public Helpers.PlayerHistory[] PlayerHistory { get; set; } public Helpers.PlayerHistory[] PlayerHistory { get; set; }
public int ID { get; set; } public long ID { get; set; }
public bool Online { get; set; } public bool Online { get; set; }
} }
} }

View File

@ -41,7 +41,7 @@ namespace SharedLibraryCore.Events
OwnerEntity = new EntityInfo() OwnerEntity = new EntityInfo()
{ {
Name = E.Owner.Hostname, Name = E.Owner.Hostname,
Id = E.Owner.GetHashCode() Id = E.Owner.EndPoint
}, },
OriginEntity = E.Origin == null ? null : new EntityInfo() OriginEntity = E.Origin == null ? null : new EntityInfo()
{ {

View File

@ -14,7 +14,7 @@ namespace SharedLibraryCore.Interfaces
Task Init(); Task Init();
void Start(); void Start();
void Stop(); void Stop();
ILogger GetLogger(int serverId); ILogger GetLogger(long serverId);
IList<Server> GetServers(); IList<Server> GetServers();
IList<Command> GetCommands(); IList<Command> GetCommands();
IList<Helpers.MessageToken> GetMessageTokens(); IList<Helpers.MessageToken> GetMessageTokens();

View File

@ -60,7 +60,7 @@ CREATE INDEX IX_EFAlias_LinkId ON EFAlias (
); );
PRAGMA foreign_keys = 1; PRAGMA foreign_keys = 1;
"); ", suppressTransaction:true);
} }
else else
{ {

View File

@ -0,0 +1,692 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SharedLibraryCore.Database;
namespace SharedLibraryCore.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")]
partial class AddEndpointToEFServerUpdateServerIdType
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.4-rtm-31024");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.Property<int>("SnapshotId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<int>("CurrentSessionLength");
b.Property<double>("CurrentStrain");
b.Property<int>("CurrentViewAngleId");
b.Property<int>("Deaths");
b.Property<double>("Distance");
b.Property<double>("EloRating");
b.Property<int>("HitDestinationId");
b.Property<int>("HitLocation");
b.Property<int>("HitOriginId");
b.Property<int>("HitType");
b.Property<int>("Hits");
b.Property<int>("Kills");
b.Property<int>("LastStrainAngleId");
b.Property<double>("SessionAngleOffset");
b.Property<double>("SessionSPM");
b.Property<int>("SessionScore");
b.Property<double>("StrainAngleBetween");
b.Property<int>("TimeSinceLastEvent");
b.Property<int>("WeaponId");
b.Property<DateTime>("When");
b.HasKey("SnapshotId");
b.HasIndex("ClientId");
b.HasIndex("CurrentViewAngleId");
b.HasIndex("HitDestinationId");
b.HasIndex("HitOriginId");
b.HasIndex("LastStrainAngleId");
b.ToTable("EFACSnapshot");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
{
b.Property<long>("KillId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AttackerId");
b.Property<int>("Damage");
b.Property<int?>("DeathOriginVector3Id");
b.Property<int>("DeathType");
b.Property<double>("Fraction");
b.Property<int>("HitLoc");
b.Property<bool>("IsKill");
b.Property<int?>("KillOriginVector3Id");
b.Property<int>("Map");
b.Property<long>("ServerId");
b.Property<int>("VictimId");
b.Property<int?>("ViewAnglesVector3Id");
b.Property<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<long>("ServerId");
b.Property<DateTime>("TimeSent");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.HasIndex("ServerId");
b.HasIndex("TimeSent");
b.ToTable("EFClientMessages");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.Property<int>("RatingHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.HasKey("RatingHistoryId");
b.HasIndex("ClientId");
b.ToTable("EFClientRatingHistory");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.Property<int>("ClientId");
b.Property<long>("ServerId");
b.Property<bool>("Active");
b.Property<int>("Deaths");
b.Property<double>("EloRating");
b.Property<int>("Kills");
b.Property<double>("MaxStrain");
b.Property<double>("RollingWeightedKDR");
b.Property<double>("SPM");
b.Property<double>("Skill");
b.Property<int>("TimePlayed");
b.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<long>("ServerId")
.HasColumnName("EFClientStatistics_ServerId");
b.HasKey("HitLocationCountId");
b.HasIndex("ServerId");
b.HasIndex("ClientId", "ServerId");
b.ToTable("EFHitLocationCounts");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
{
b.Property<int>("RatingId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ActivityAmount");
b.Property<bool>("Newest");
b.Property<double>("Performance");
b.Property<int>("Ranking");
b.Property<int>("RatingHistoryId");
b.Property<long?>("ServerId");
b.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("Performance");
b.HasIndex("Ranking");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<long>("ServerId");
b.Property<bool>("Active");
b.Property<string>("EndPoint");
b.Property<int>("Port");
b.HasKey("ServerId");
b.ToTable("EFServers");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
{
b.Property<int>("StatisticId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<long>("ServerId");
b.Property<long>("TotalKills");
b.Property<long>("TotalPlayTime");
b.HasKey("StatisticId");
b.HasIndex("ServerId");
b.ToTable("EFServerStatistics");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
{
b.Property<int>("AliasId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<DateTime>("DateAdded");
b.Property<int?>("IPAddress");
b.Property<int>("LinkId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
b.HasIndex("LinkId");
b.HasIndex("Name");
b.ToTable("EFAlias");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
{
b.Property<int>("AliasLinkId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.HasKey("AliasLinkId");
b.ToTable("EFAliasLinks");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
{
b.Property<int>("ChangeHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("Comment")
.HasMaxLength(128);
b.Property<string>("CurrentValue");
b.Property<int>("OriginEntityId");
b.Property<string>("PreviousValue");
b.Property<int>("TargetEntityId");
b.Property<DateTime>("TimeChanged");
b.Property<int>("TypeOfChange");
b.HasKey("ChangeHistoryId");
b.ToTable("EFChangeHistory");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.Property<int>("ClientId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AliasLinkId");
b.Property<int>("Connections");
b.Property<int>("CurrentAliasId");
b.Property<DateTime>("FirstConnection");
b.Property<DateTime>("LastConnection");
b.Property<int>("Level");
b.Property<bool>("Masked");
b.Property<long>("NetworkId");
b.Property<string>("Password");
b.Property<string>("PasswordSalt");
b.Property<int>("TotalConnectionTime");
b.HasKey("ClientId");
b.HasIndex("AliasLinkId");
b.HasIndex("CurrentAliasId");
b.HasIndex("NetworkId")
.IsUnique();
b.ToTable("EFClients");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.Property<int>("MetaId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<DateTime>("Created");
b.Property<string>("Extra");
b.Property<string>("Key")
.IsRequired();
b.Property<DateTime>("Updated");
b.Property<string>("Value")
.IsRequired();
b.HasKey("MetaId");
b.HasIndex("ClientId");
b.ToTable("EFMeta");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.Property<int>("PenaltyId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("AutomatedOffense");
b.Property<DateTime?>("Expires");
b.Property<int>("LinkId");
b.Property<int>("OffenderId");
b.Property<string>("Offense")
.IsRequired();
b.Property<int>("PunisherId");
b.Property<int>("Type");
b.Property<DateTime>("When");
b.HasKey("PenaltyId");
b.HasIndex("LinkId");
b.HasIndex("OffenderId");
b.HasIndex("PunisherId");
b.ToTable("EFPenalties");
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.Property<int>("Vector3Id")
.ValueGeneratedOnAdd();
b.Property<int?>("EFACSnapshotSnapshotId");
b.Property<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.HasIndex("EFACSnapshotSnapshotId");
b.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
.WithMany()
.HasForeignKey("HitDestinationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
.WithMany()
.HasForeignKey("HitOriginId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
.WithMany()
.HasForeignKey("LastStrainAngleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
.WithMany()
.HasForeignKey("AttackerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
.WithMany()
.HasForeignKey("DeathOriginVector3Id");
b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
.WithMany()
.HasForeignKey("KillOriginVector3Id");
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
.WithMany()
.HasForeignKey("VictimId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
.WithMany()
.HasForeignKey("ViewAnglesVector3Id");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
.WithMany("HitLocations")
.HasForeignKey("ClientId", "ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
.WithMany("Ratings")
.HasForeignKey("RatingHistoryId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
.WithMany("Children")
.HasForeignKey("LinkId")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
.WithMany()
.HasForeignKey("AliasLinkId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
.WithMany()
.HasForeignKey("CurrentAliasId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany("Meta")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
.WithMany("ReceivedPenalties")
.HasForeignKey("LinkId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
.WithMany("ReceivedPenalties")
.HasForeignKey("OffenderId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
.WithMany("AdministeredPenalties")
.HasForeignKey("PunisherId")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
.WithMany("PredictedViewAngles")
.HasForeignKey("EFACSnapshotSnapshotId");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace SharedLibraryCore.Migrations
{
public partial class AddEndpointToEFServerUpdateServerIdType : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "EndPoint",
table: "EFServers",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "EndPoint",
table: "EFServers");
}
}
}

View File

@ -105,7 +105,7 @@ namespace SharedLibraryCore.Migrations
b.Property<int>("Map"); b.Property<int>("Map");
b.Property<int>("ServerId"); b.Property<long>("ServerId");
b.Property<int>("VictimId"); b.Property<int>("VictimId");
@ -145,7 +145,7 @@ namespace SharedLibraryCore.Migrations
b.Property<string>("Message"); b.Property<string>("Message");
b.Property<int>("ServerId"); b.Property<long>("ServerId");
b.Property<DateTime>("TimeSent"); b.Property<DateTime>("TimeSent");
@ -180,7 +180,7 @@ namespace SharedLibraryCore.Migrations
{ {
b.Property<int>("ClientId"); b.Property<int>("ClientId");
b.Property<int>("ServerId"); b.Property<long>("ServerId");
b.Property<bool>("Active"); b.Property<bool>("Active");
@ -227,7 +227,7 @@ namespace SharedLibraryCore.Migrations
b.Property<float>("MaxAngleDistance"); b.Property<float>("MaxAngleDistance");
b.Property<int>("ServerId") b.Property<long>("ServerId")
.HasColumnName("EFClientStatistics_ServerId"); .HasColumnName("EFClientStatistics_ServerId");
b.HasKey("HitLocationCountId"); b.HasKey("HitLocationCountId");
@ -256,7 +256,7 @@ namespace SharedLibraryCore.Migrations
b.Property<int>("RatingHistoryId"); b.Property<int>("RatingHistoryId");
b.Property<int?>("ServerId"); b.Property<long?>("ServerId");
b.Property<DateTime>("When"); b.Property<DateTime>("When");
@ -277,10 +277,12 @@ namespace SharedLibraryCore.Migrations
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{ {
b.Property<int>("ServerId"); b.Property<long>("ServerId");
b.Property<bool>("Active"); b.Property<bool>("Active");
b.Property<string>("EndPoint");
b.Property<int>("Port"); b.Property<int>("Port");
b.HasKey("ServerId"); b.HasKey("ServerId");
@ -295,7 +297,7 @@ namespace SharedLibraryCore.Migrations
b.Property<bool>("Active"); b.Property<bool>("Active");
b.Property<int>("ServerId"); b.Property<long>("ServerId");
b.Property<long>("TotalKills"); b.Property<long>("TotalKills");

View File

@ -33,7 +33,7 @@ namespace SharedLibraryCore
IP = config.IPAddress; IP = config.IPAddress;
Port = config.Port; Port = config.Port;
Manager = mgr; Manager = mgr;
Logger = Manager.GetLogger(this.GetHashCode()); Logger = Manager.GetLogger(this.EndPoint);
Logger.WriteInfo(this.ToString()); Logger.WriteInfo(this.ToString());
ServerConfig = config; ServerConfig = config;
RemoteConnection = new RCon.Connection(IP, Port, Password, Logger); RemoteConnection = new RCon.Connection(IP, Port, Password, Logger);
@ -49,6 +49,8 @@ namespace SharedLibraryCore
InitializeAutoMessages(); InitializeAutoMessages();
} }
public long EndPoint => Convert.ToInt64($"{IP.Replace(".", "")}{Port}");
//Returns current server IP set by `net_ip` -- *STRING* //Returns current server IP set by `net_ip` -- *STRING*
public String GetIP() public String GetIP()
{ {

View File

@ -13,6 +13,12 @@
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\20181126232438_AddEndpointToEFServer.cs" />
<Compile Remove="Migrations\20181126233300_AddEndpointToEFServer.cs" />
<Compile Remove="Migrations\20181127143920_AddEndpointToEFServerUpdateServerIdType.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Jint" Version="2.11.58" /> <PackageReference Include="Jint" Version="2.11.58" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.4" />

View File

@ -25,7 +25,7 @@ namespace WebfrontCore.Controllers.API
var serverInfo = Manager.GetServers() var serverInfo = Manager.GetServers()
.Select(server => new .Select(server => new
{ {
Id = server.GetHashCode(), Id = server.EndPoint,
Name = server.Hostname, Name = server.Hostname,
MaxPlayers = server.MaxClients, MaxPlayers = server.MaxClients,
CurrentPlayers = server.GetClientsAsList().Count, CurrentPlayers = server.GetClientsAsList().Count,

View File

@ -79,7 +79,7 @@ namespace WebfrontCore.Controllers
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
{ {
serverId = server.GetHashCode(), serverId = server.EndPoint,
command command
})); }));
} }
@ -110,7 +110,7 @@ namespace WebfrontCore.Controllers
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
{ {
serverId = server.GetHashCode(), serverId = server.EndPoint,
command = $"!unban @{targetId} {Reason}" command = $"!unban @{targetId} {Reason}"
})); }));
} }
@ -178,7 +178,7 @@ namespace WebfrontCore.Controllers
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
{ {
serverId = server.GetHashCode(), serverId = server.EndPoint,
command = $"!setlevel @{targetId} {level}" command = $"!setlevel @{targetId} {level}"
})); }));
} }

View File

@ -2,8 +2,6 @@
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -17,7 +15,7 @@ namespace WebfrontCore.Controllers
var activeServers = Manager.GetServers().Select(s => new ServerInfo() var activeServers = Manager.GetServers().Select(s => new ServerInfo()
{ {
Name = s.Hostname, Name = s.Hostname,
ID = s.GetHashCode(), ID = s.EndPoint,
}); });
ViewBag.Description = "Use the IW4MAdmin web console to execute commands"; ViewBag.Description = "Use the IW4MAdmin web console to execute commands";
@ -27,9 +25,10 @@ namespace WebfrontCore.Controllers
return View(activeServers); return View(activeServers);
} }
public async Task<IActionResult> ExecuteAsync(int serverId, string command) public async Task<IActionResult> ExecuteAsync(long serverId, string command)
{ {
var server = Manager.GetServers().First(s => s.GetHashCode() == serverId); var server = Manager.GetServers().First(s => s.EndPoint == serverId);
var client = new EFClient() var client = new EFClient()
{ {
ClientId = Client.ClientId, ClientId = Client.ClientId,

View File

@ -1,10 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace WebfrontCore.Controllers namespace WebfrontCore.Controllers
{ {
@ -12,16 +9,19 @@ namespace WebfrontCore.Controllers
{ {
[HttpGet] [HttpGet]
[ResponseCache(NoStore = true, Duration = 0)] [ResponseCache(NoStore = true, Duration = 0)]
public IActionResult ClientActivity(int id) public IActionResult ClientActivity(long id)
{ {
var s = Manager.GetServers().FirstOrDefault(s2 => s2.GetHashCode() == id); var s = Manager.GetServers().FirstOrDefault(s2 => s2.EndPoint == id);
if (s == null) if (s == null)
{
return View("Error", "Invalid server!"); return View("Error", "Invalid server!");
}
var serverInfo = new ServerInfo() var serverInfo = new ServerInfo()
{ {
Name = s.Hostname, Name = s.Hostname,
ID = s.GetHashCode(), ID = s.EndPoint,
Port = s.GetPort(), Port = s.GetPort(),
Map = s.CurrentMap.Alias, Map = s.CurrentMap.Alias,
ClientCount = s.ClientNum, ClientCount = s.ClientNum,

View File

@ -13,7 +13,7 @@ namespace WebfrontCore.ViewComponents
var serverInfo = servers.Select(s => new ServerInfo() var serverInfo = servers.Select(s => new ServerInfo()
{ {
Name = s.Hostname, Name = s.Hostname,
ID = s.GetHashCode(), ID = s.EndPoint,
Port = s.GetPort(), Port = s.GetPort(),
Map = s.CurrentMap.Alias, Map = s.CurrentMap.Alias,
ClientCount = s.ClientNum, ClientCount = s.ClientNum,