update project to .net core 2.1.5
got rid of "threadsafe" stats service in stats plugin
This commit is contained in:
parent
c8366a22e5
commit
b289917319
@ -3,9 +3,10 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
||||
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
||||
<Version>2.1.9.4</Version>
|
||||
<Version>2.1.9.5</Version>
|
||||
<Authors>RaidMax</Authors>
|
||||
<Company>Forever None</Company>
|
||||
<Product>IW4MAdmin</Product>
|
||||
@ -30,8 +31,8 @@
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<AssemblyVersion>2.1.9.4</AssemblyVersion>
|
||||
<FileVersion>2.1.9.4</FileVersion>
|
||||
<AssemblyVersion>2.1.9.5</AssemblyVersion>
|
||||
<FileVersion>2.1.9.5</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -78,7 +79,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
|
@ -20,11 +20,37 @@ namespace IW4MAdmin.Application
|
||||
|
||||
readonly string FileName;
|
||||
readonly SemaphoreSlim OnLogWriting;
|
||||
static readonly short MAX_LOG_FILES = 10;
|
||||
|
||||
public Logger(string fn)
|
||||
{
|
||||
FileName = Path.Join("Log", $"{fn}-{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.log");
|
||||
OnLogWriting = new SemaphoreSlim(1,1);
|
||||
FileName = Path.Join("Log", $"{fn}.log");
|
||||
OnLogWriting = new SemaphoreSlim(1, 1);
|
||||
RotateLogs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// rotates logs when log is initialized
|
||||
/// </summary>
|
||||
private void RotateLogs()
|
||||
{
|
||||
string maxLog = FileName + MAX_LOG_FILES;
|
||||
|
||||
if (File.Exists(maxLog))
|
||||
{
|
||||
File.Delete(maxLog);
|
||||
}
|
||||
|
||||
for (int i = MAX_LOG_FILES - 1; i >= 0; i--)
|
||||
{
|
||||
string logToMove = i == 0 ? FileName : FileName + i;
|
||||
string movedLogName = FileName + (i + 1);
|
||||
|
||||
if (File.Exists(logToMove))
|
||||
{
|
||||
File.Move(logToMove, movedLogName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Write(string msg, LogType type)
|
||||
@ -41,17 +67,25 @@ namespace IW4MAdmin.Application
|
||||
catch (Exception) { }
|
||||
|
||||
string LogLine = $"[{DateTime.Now.ToString("MM.dd.yyy HH:mm:ss.fff")}] - {stringType}: {msg}";
|
||||
try
|
||||
{
|
||||
#if DEBUG
|
||||
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
|
||||
|
||||
Console.WriteLine(LogLine);
|
||||
File.AppendAllText(FileName, LogLine + Environment.NewLine);
|
||||
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
|
||||
Console.WriteLine(LogLine);
|
||||
File.AppendAllText(FileName, LogLine + Environment.NewLine);
|
||||
#else
|
||||
if (type == LogType.Error || type == LogType.Verbose)
|
||||
Console.WriteLine(LogLine);
|
||||
//if (type != LogType.Debug)
|
||||
File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}");
|
||||
#endif
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Well.. It looks like your machine can't event write to the log file. That's something else...");
|
||||
Console.WriteLine(ex.GetExceptionInfo());
|
||||
}
|
||||
|
||||
OnLogWriting.Release(1);
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ namespace IW4MAdmin.Application
|
||||
var consoleTask = Task.Run(async () =>
|
||||
{
|
||||
String userInput;
|
||||
Player Origin = Utilities.IW4MAdminClient;
|
||||
Player Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]);
|
||||
|
||||
do
|
||||
{
|
||||
@ -123,7 +123,6 @@ namespace IW4MAdmin.Application
|
||||
|
||||
if (userInput?.Length > 0)
|
||||
{
|
||||
Origin.CurrentServer = ServerManager.Servers[0];
|
||||
GameEvent E = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Command,
|
||||
|
@ -205,8 +205,7 @@ namespace IW4MAdmin
|
||||
if (currentBan != null)
|
||||
{
|
||||
Logger.WriteInfo($"Banned client {player} trying to connect...");
|
||||
var autoKickClient = Utilities.IW4MAdminClient;
|
||||
autoKickClient.CurrentServer = this;
|
||||
var autoKickClient = Utilities.IW4MAdminClient(this);
|
||||
|
||||
// the player is permanently banned
|
||||
if (currentBan.Type == Penalty.PenaltyType.Ban)
|
||||
@ -911,7 +910,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
if (Target.Warnings >= 4)
|
||||
{
|
||||
Target.Kick(loc["SERVER_WARNLIMT_REACHED"], Utilities.IW4MAdminClient);
|
||||
Target.Kick(loc["SERVER_WARNLIMT_REACHED"], Utilities.IW4MAdminClient(this));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
@ -17,7 +18,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App"/>
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.Plugins.Login</PackageId>
|
||||
@ -21,7 +22,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App"/>
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.Plugins.ProfanityDeterment</PackageId>
|
||||
@ -19,7 +20,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App"/>
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
|
@ -28,7 +28,6 @@ var plugin = {
|
||||
var re = cl.GetAsync('https://api.xdefcon.com/proxy/check/?ip=' + origin.IPAddressString).Result;
|
||||
var co = re.Content;
|
||||
var parsedJSON = JSON.parse(co.ReadAsStringAsync().Result);
|
||||
// todo: does this work as expected now?
|
||||
co.Dispose();
|
||||
re.Dispose();
|
||||
cl.Dispose();
|
||||
@ -39,11 +38,7 @@ var plugin = {
|
||||
|
||||
if (usingVPN) {
|
||||
this.logger.WriteInfo(origin + ' is using a VPN (' + origin.IPAddressString + ')');
|
||||
var library = importNamespace('SharedLibraryCore');
|
||||
var kickOrigin = new library.Objects.Player();
|
||||
kickOrigin.ClientId = 1;
|
||||
kickOrigin.CurrentServer = origin.CurrentServer;
|
||||
origin.Kick(_localization.LocalizationIndex["SERVER_KICK_VPNS_NOTALLOWED"], kickOrigin);
|
||||
origin.Kick(_localization.LocalizationIndex["SERVER_KICK_VPNS_NOTALLOWED"], _IW4MAdminClient);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -6,6 +6,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharedLibraryCore.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IW4MAdmin.Plugins.Stats.Commands
|
||||
{
|
||||
@ -17,23 +19,30 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
||||
{
|
||||
if (E.Origin.ClientNumber >= 0)
|
||||
{
|
||||
var svc = new SharedLibraryCore.Services.GenericRepository<EFClientStatistics>();
|
||||
|
||||
int serverId = E.Owner.GetHashCode();
|
||||
var stats = svc.Find(s => s.ClientId == E.Origin.ClientId && s.ServerId == serverId).First();
|
||||
|
||||
stats.Deaths = 0;
|
||||
stats.Kills = 0;
|
||||
stats.SPM = 0.0;
|
||||
stats.Skill = 0.0;
|
||||
stats.TimePlayed = 0;
|
||||
// todo: make this more dynamic
|
||||
stats.EloRating = 200.0;
|
||||
EFClientStatistics clientStats;
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
clientStats = await ctx.Set<EFClientStatistics>()
|
||||
.Where(s => s.ClientId == E.Origin.ClientId && s.ServerId == serverId)
|
||||
.FirstAsync();
|
||||
|
||||
// reset the cached version
|
||||
Plugin.Manager.ResetStats(E.Origin.ClientId, E.Owner.GetHashCode());
|
||||
clientStats.Deaths = 0;
|
||||
clientStats.Kills = 0;
|
||||
clientStats.SPM = 0.0;
|
||||
clientStats.Skill = 0.0;
|
||||
clientStats.TimePlayed = 0;
|
||||
// todo: make this more dynamic
|
||||
clientStats.EloRating = 200.0;
|
||||
|
||||
// fixme: this doesn't work properly when another context exists
|
||||
await svc.SaveChangesAsync();
|
||||
// reset the cached version
|
||||
Plugin.Manager.ResetStats(E.Origin.ClientId, E.Owner.GetHashCode());
|
||||
|
||||
// fixme: this doesn't work properly when another context exists
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_RESET_SUCCESS"]);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharedLibraryCore.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IW4MAdmin.Plugins.Stats.Commands
|
||||
{
|
||||
@ -39,19 +41,21 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
||||
}
|
||||
}
|
||||
|
||||
var clientStats = new GenericRepository<EFClientStatistics>();
|
||||
int serverId = E.Owner.GetHashCode();
|
||||
|
||||
if (E.Target != null)
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
pStats = (await clientStats.FindAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId)).First();
|
||||
statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()}";
|
||||
}
|
||||
if (E.Target != null)
|
||||
{
|
||||
pStats = (await ctx.Set<EFClientStatistics>().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId));
|
||||
statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()}";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pStats = (await clientStats.FindAsync(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)).First();
|
||||
statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()}";
|
||||
else
|
||||
{
|
||||
pStats = (await ctx.Set<EFClientStatistics>().FirstAsync((c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)));
|
||||
statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()}";
|
||||
}
|
||||
}
|
||||
|
||||
if (E.Message.IsBroadcastCommand())
|
||||
|
@ -24,20 +24,20 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
public class StatManager
|
||||
{
|
||||
private ConcurrentDictionary<int, ServerStats> Servers;
|
||||
private ConcurrentDictionary<int, ThreadSafeStatsService> ContextThreads;
|
||||
private ILogger Log;
|
||||
private IManager Manager;
|
||||
private readonly IManager Manager;
|
||||
|
||||
|
||||
private readonly SemaphoreSlim OnProcessingPenalty;
|
||||
private readonly SemaphoreSlim OnProcessingSensitive;
|
||||
|
||||
public StatManager(IManager mgr)
|
||||
{
|
||||
Servers = new ConcurrentDictionary<int, ServerStats>();
|
||||
ContextThreads = new ConcurrentDictionary<int, ThreadSafeStatsService>();
|
||||
Log = mgr.GetLogger(0);
|
||||
Manager = mgr;
|
||||
OnProcessingPenalty = new SemaphoreSlim(1, 1);
|
||||
OnProcessingSensitive = new SemaphoreSlim(1, 1);
|
||||
}
|
||||
|
||||
public EFClientStatistics GetClientStats(int clientId, int serverId) => Servers[serverId].PlayerStats[clientId];
|
||||
@ -188,36 +188,36 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
/// <param name="sv"></param>
|
||||
public void AddServer(Server sv)
|
||||
{
|
||||
// insert the server if it does not exist
|
||||
try
|
||||
{
|
||||
int serverId = sv.GetHashCode();
|
||||
var statsSvc = new ThreadSafeStatsService();
|
||||
ContextThreads.TryAdd(serverId, statsSvc);
|
||||
EFServer server;
|
||||
|
||||
var serverSvc = statsSvc.ServerSvc;
|
||||
|
||||
// get the server from the database if it exists, otherwise create and insert a new one
|
||||
var server = statsSvc.ServerSvc.Find(c => c.ServerId == serverId).FirstOrDefault();
|
||||
|
||||
if (server == null)
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
server = new EFServer()
|
||||
{
|
||||
Port = sv.GetPort(),
|
||||
Active = true,
|
||||
ServerId = serverId
|
||||
};
|
||||
var serverSet = ctx.Set<EFServer>();
|
||||
// get the server from the database if it exists, otherwise create and insert a new one
|
||||
server = serverSet.FirstOrDefault(c => c.ServerId == serverId);
|
||||
|
||||
serverSvc.Insert(server);
|
||||
if (server == null)
|
||||
{
|
||||
server = new EFServer()
|
||||
{
|
||||
Port = sv.GetPort(),
|
||||
Active = true,
|
||||
ServerId = serverId
|
||||
};
|
||||
|
||||
server = serverSet.Add(server).Entity;
|
||||
// this doesn't need to be async as it's during initialization
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
// this doesn't need to be async as it's during initialization
|
||||
serverSvc.SaveChanges();
|
||||
// check to see if the stats have ever been initialized
|
||||
InitializeServerStats(sv);
|
||||
statsSvc.ServerStatsSvc.SaveChanges();
|
||||
var serverStats = InitializeServerStats(sv);
|
||||
|
||||
var serverStats = statsSvc.ServerStatsSvc.Find(c => c.ServerId == serverId).FirstOrDefault();
|
||||
Servers.TryAdd(serverId, new ServerStats(server, serverStats)
|
||||
{
|
||||
IsTeamBased = sv.Gametype != "dm"
|
||||
@ -237,106 +237,134 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
/// <returns>EFClientStatistic of specified player</returns>
|
||||
public async Task<EFClientStatistics> AddPlayer(Player pl)
|
||||
{
|
||||
int serverId = pl.CurrentServer.GetHashCode();
|
||||
await OnProcessingSensitive.WaitAsync();
|
||||
|
||||
if (!Servers.ContainsKey(serverId))
|
||||
try
|
||||
{
|
||||
Log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
|
||||
return null;
|
||||
}
|
||||
int serverId = pl.CurrentServer.GetHashCode();
|
||||
|
||||
var playerStats = Servers[serverId].PlayerStats;
|
||||
var detectionStats = Servers[serverId].PlayerDetections;
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
|
||||
if (playerStats.ContainsKey(pl.ClientId))
|
||||
{
|
||||
Log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId}");
|
||||
return playerStats[pl.ClientId];
|
||||
}
|
||||
|
||||
// get the client's stats from the database if it exists, otherwise create and attach a new one
|
||||
// if this fails we want to throw an exception
|
||||
var clientStatsSvc = statsSvc.ClientStatSvc;
|
||||
var clientStats = clientStatsSvc.Find(c => c.ClientId == pl.ClientId && c.ServerId == serverId).FirstOrDefault();
|
||||
|
||||
if (clientStats == null)
|
||||
{
|
||||
clientStats = new EFClientStatistics()
|
||||
if (!Servers.ContainsKey(serverId))
|
||||
{
|
||||
Active = true,
|
||||
ClientId = pl.ClientId,
|
||||
Deaths = 0,
|
||||
Kills = 0,
|
||||
ServerId = serverId,
|
||||
Skill = 0.0,
|
||||
SPM = 0.0,
|
||||
EloRating = 200.0,
|
||||
HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType<IW4Info.HitLocation>().Select(hl => new EFHitLocationCount()
|
||||
{
|
||||
Active = true,
|
||||
HitCount = 0,
|
||||
Location = hl
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
// insert if they've not been added
|
||||
clientStats = clientStatsSvc.Insert(clientStats);
|
||||
|
||||
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
|
||||
{
|
||||
Log.WriteWarning("Adding new client to stats failed");
|
||||
Log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
|
||||
return null;
|
||||
}
|
||||
|
||||
await clientStatsSvc.SaveChangesAsync();
|
||||
}
|
||||
var playerStats = Servers[serverId].PlayerStats;
|
||||
var detectionStats = Servers[serverId].PlayerDetections;
|
||||
|
||||
else
|
||||
{
|
||||
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
|
||||
if (playerStats.ContainsKey(pl.ClientId))
|
||||
{
|
||||
Log.WriteWarning("Adding pre-existing client to stats failed");
|
||||
Log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId}");
|
||||
return playerStats[pl.ClientId];
|
||||
}
|
||||
}
|
||||
|
||||
// migration for previous existing stats
|
||||
if (clientStats.HitLocations.Count == 0)
|
||||
{
|
||||
clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType<IW4Info.HitLocation>()
|
||||
.Select(hl => new EFHitLocationCount()
|
||||
// get the client's stats from the database if it exists, otherwise create and attach a new one
|
||||
// if this fails we want to throw an exception
|
||||
|
||||
EFClientStatistics clientStats;
|
||||
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
var clientStatsSet = ctx.Set<EFClientStatistics>();
|
||||
clientStats = clientStatsSet
|
||||
.Include(cl => cl.HitLocations)
|
||||
.FirstOrDefault(c => c.ClientId == pl.ClientId && c.ServerId == serverId);
|
||||
|
||||
if (clientStats == null)
|
||||
{
|
||||
Active = true,
|
||||
HitCount = 0,
|
||||
Location = hl
|
||||
})
|
||||
.ToList();
|
||||
await statsSvc.ClientStatSvc.SaveChangesAsync();
|
||||
clientStats = new EFClientStatistics()
|
||||
{
|
||||
Active = true,
|
||||
ClientId = pl.ClientId,
|
||||
Deaths = 0,
|
||||
Kills = 0,
|
||||
ServerId = serverId,
|
||||
Skill = 0.0,
|
||||
SPM = 0.0,
|
||||
EloRating = 200.0,
|
||||
HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType<IW4Info.HitLocation>().Select(hl => new EFHitLocationCount()
|
||||
{
|
||||
Active = true,
|
||||
HitCount = 0,
|
||||
Location = hl
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
// insert if they've not been added
|
||||
clientStats = clientStatsSet.Add(clientStats).Entity;
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
|
||||
{
|
||||
Log.WriteWarning("Adding new client to stats failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
|
||||
{
|
||||
Log.WriteWarning("Adding pre-existing client to stats failed");
|
||||
}
|
||||
}
|
||||
|
||||
// migration for previous existing stats
|
||||
if (clientStats.HitLocations.Count == 0)
|
||||
{
|
||||
clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType<IW4Info.HitLocation>()
|
||||
.Select(hl => new EFHitLocationCount()
|
||||
{
|
||||
Active = true,
|
||||
HitCount = 0,
|
||||
Location = hl
|
||||
})
|
||||
.ToList();
|
||||
|
||||
ctx.Update(clientStats);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// for stats before rating
|
||||
if (clientStats.EloRating == 0.0)
|
||||
{
|
||||
clientStats.EloRating = clientStats.Skill;
|
||||
}
|
||||
|
||||
if (clientStats.RollingWeightedKDR == 0)
|
||||
{
|
||||
clientStats.RollingWeightedKDR = clientStats.KDR;
|
||||
}
|
||||
|
||||
// set these on connecting
|
||||
clientStats.LastActive = DateTime.UtcNow;
|
||||
clientStats.LastStatCalculation = DateTime.UtcNow;
|
||||
clientStats.SessionScore = pl.Score;
|
||||
clientStats.LastScore = pl.Score;
|
||||
|
||||
if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)))
|
||||
{
|
||||
Log.WriteWarning("Could not add client to detection");
|
||||
}
|
||||
|
||||
Log.WriteInfo($"Adding {pl} to stats");
|
||||
}
|
||||
|
||||
return clientStats;
|
||||
}
|
||||
|
||||
// for stats before rating
|
||||
if (clientStats.EloRating == 0.0)
|
||||
catch (Exception ex)
|
||||
{
|
||||
clientStats.EloRating = clientStats.Skill;
|
||||
|
||||
}
|
||||
|
||||
if (clientStats.RollingWeightedKDR == 0)
|
||||
finally
|
||||
{
|
||||
clientStats.RollingWeightedKDR = clientStats.KDR;
|
||||
OnProcessingSensitive.Release(1);
|
||||
}
|
||||
|
||||
// set these on connecting
|
||||
clientStats.LastActive = DateTime.UtcNow;
|
||||
clientStats.LastStatCalculation = DateTime.UtcNow;
|
||||
clientStats.SessionScore = pl.Score;
|
||||
clientStats.LastScore = pl.Score;
|
||||
|
||||
if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)))
|
||||
{
|
||||
Log.WriteWarning("Could not add client to detection");
|
||||
}
|
||||
|
||||
Log.WriteInfo($"Adding {pl} to stats");
|
||||
return clientStats;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -352,7 +380,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
var playerStats = Servers[serverId].PlayerStats;
|
||||
var detectionStats = Servers[serverId].PlayerDetections;
|
||||
var serverStats = Servers[serverId].ServerStatistics;
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
|
||||
if (!playerStats.ContainsKey(pl.ClientId))
|
||||
{
|
||||
@ -371,10 +398,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue4);
|
||||
|
||||
// sync their stats before they leave
|
||||
var clientStatsSvc = statsSvc.ClientStatSvc;
|
||||
clientStats = UpdateStats(clientStats);
|
||||
clientStatsSvc.Update(clientStats);
|
||||
await clientStatsSvc.SaveChangesAsync();
|
||||
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
ctx.Update(clientStats);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// increment the total play time
|
||||
serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds;
|
||||
@ -405,15 +435,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads,
|
||||
string fraction, string visibilityPercentage, string snapAngles)
|
||||
{
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
|
||||
// incase the add palyer event get delayed
|
||||
if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
|
||||
{
|
||||
await AddPlayer(attacker);
|
||||
}
|
||||
|
||||
|
||||
Vector3 vDeathOrigin = null;
|
||||
Vector3 vKillOrigin = null;
|
||||
Vector3 vViewAngles = null;
|
||||
@ -490,10 +511,20 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
return;
|
||||
}
|
||||
|
||||
// incase the add palyer event get delayed
|
||||
if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
|
||||
{
|
||||
await AddPlayer(attacker);
|
||||
}
|
||||
|
||||
var clientDetection = Servers[serverId].PlayerDetections[attacker.ClientId];
|
||||
var clientStats = Servers[serverId].PlayerStats[attacker.ClientId];
|
||||
var clientStatsSvc = statsSvc.ClientStatSvc;
|
||||
clientStatsSvc.Update(clientStats);
|
||||
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
ctx.Set<EFClientStatistics>().Update(clientStats);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// increment their hit count
|
||||
if (hit.DeathType == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET ||
|
||||
@ -531,17 +562,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
Log.WriteDebug(ex.GetExceptionInfo());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await clientStatsSvc.SaveChangesAsync();
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("Could save save client stats");
|
||||
Log.WriteDebug(ex.GetExceptionInfo());
|
||||
}
|
||||
|
||||
OnProcessingPenalty.Release(1);
|
||||
}
|
||||
}
|
||||
@ -743,10 +763,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
}
|
||||
|
||||
// todo: do we want to save this immediately?
|
||||
var clientStatsSvc = ContextThreads[serverId].ClientStatSvc;
|
||||
clientStatsSvc.Update(attackerStats);
|
||||
clientStatsSvc.Update(victimStats);
|
||||
await clientStatsSvc.SaveChangesAsync();
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
var clientStatsSet = ctx.Set<EFClientStatistics>();
|
||||
|
||||
clientStatsSet.Update(attackerStats);
|
||||
clientStatsSet.Update(victimStats);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1079,39 +1103,43 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
return clientStats;
|
||||
}
|
||||
|
||||
public void InitializeServerStats(Server sv)
|
||||
public EFServerStatistics InitializeServerStats(Server sv)
|
||||
{
|
||||
int serverId = sv.GetHashCode();
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
EFServerStatistics serverStats;
|
||||
|
||||
var serverStats = statsSvc.ServerStatsSvc.Find(s => s.ServerId == serverId).FirstOrDefault();
|
||||
if (serverStats == null)
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
Log.WriteDebug($"Initializing server stats for {sv}");
|
||||
// server stats have never been generated before
|
||||
serverStats = new EFServerStatistics()
|
||||
var serverStatsSet = ctx.Set<EFServerStatistics>();
|
||||
serverStats = serverStatsSet.FirstOrDefault(s => s.ServerId == serverId);
|
||||
|
||||
if (serverStats == null)
|
||||
{
|
||||
Active = true,
|
||||
ServerId = serverId,
|
||||
TotalKills = 0,
|
||||
TotalPlayTime = 0,
|
||||
};
|
||||
Log.WriteDebug($"Initializing server stats for {sv}");
|
||||
// server stats have never been generated before
|
||||
serverStats = new EFServerStatistics()
|
||||
{
|
||||
ServerId = serverId,
|
||||
TotalKills = 0,
|
||||
TotalPlayTime = 0,
|
||||
};
|
||||
|
||||
var ieClientStats = statsSvc.ClientStatSvc.Find(cs => cs.ServerId == serverId);
|
||||
|
||||
// set these incase we've imported settings
|
||||
serverStats.TotalKills = ieClientStats.Sum(cs => cs.Kills);
|
||||
serverStats.TotalPlayTime = Manager.GetClientService().GetTotalPlayTime().Result;
|
||||
|
||||
statsSvc.ServerStatsSvc.Insert(serverStats);
|
||||
serverStats = serverStatsSet.Add(serverStats).Entity;
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
return serverStats;
|
||||
}
|
||||
|
||||
public void ResetKillstreaks(int serverId)
|
||||
{
|
||||
var serverStats = Servers[serverId];
|
||||
|
||||
foreach (var stat in serverStats.PlayerStats.Values)
|
||||
{
|
||||
stat.StartNewSession();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetStats(int clientId, int serverId)
|
||||
@ -1131,33 +1159,30 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
if (clientId < 1)
|
||||
return;
|
||||
|
||||
var messageSvc = ContextThreads[serverId].MessageSvc;
|
||||
messageSvc.Insert(new EFClientMessage()
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
Active = true,
|
||||
ClientId = clientId,
|
||||
Message = message,
|
||||
ServerId = serverId,
|
||||
TimeSent = DateTime.UtcNow
|
||||
});
|
||||
await messageSvc.SaveChangesAsync();
|
||||
ctx.Set<EFClientMessage>().Add(new EFClientMessage()
|
||||
{
|
||||
ClientId = clientId,
|
||||
Message = message,
|
||||
ServerId = serverId,
|
||||
TimeSent = DateTime.UtcNow
|
||||
});
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Sync(Server sv)
|
||||
{
|
||||
int serverId = sv.GetHashCode();
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
var serverSvc = statsSvc.ServerSvc;
|
||||
|
||||
serverSvc.Update(Servers[serverId].Server);
|
||||
await serverSvc.SaveChangesAsync();
|
||||
|
||||
await statsSvc.KillStatsSvc.SaveChangesAsync();
|
||||
await statsSvc.ServerSvc.SaveChangesAsync();
|
||||
|
||||
statsSvc = null;
|
||||
// this should prevent the gunk from having a long lasting context.
|
||||
ContextThreads[serverId] = new ThreadSafeStatsService();
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
var serverSet = ctx.Set<EFServer>();
|
||||
serverSet.Update(Servers[serverId].Server);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTeamBased(int serverId, bool isTeamBased)
|
||||
|
@ -1,43 +0,0 @@
|
||||
using SharedLibraryCore.Services;
|
||||
using IW4MAdmin.Plugins.Stats.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
{
|
||||
public class ThreadSafeStatsService
|
||||
{
|
||||
public GenericRepository<EFClientStatistics> ClientStatSvc
|
||||
{
|
||||
get
|
||||
{
|
||||
return new GenericRepository<EFClientStatistics>(false);
|
||||
}
|
||||
}
|
||||
public GenericRepository<EFServer> ServerSvc
|
||||
{
|
||||
get
|
||||
{
|
||||
return new GenericRepository<EFServer>(false);
|
||||
}
|
||||
}
|
||||
public GenericRepository<EFClientKill> KillStatsSvc { get; private set; }
|
||||
public GenericRepository<EFServerStatistics> ServerStatsSvc { get; private set; }
|
||||
public GenericRepository<EFClientMessage> MessageSvc
|
||||
{
|
||||
get
|
||||
{
|
||||
return new GenericRepository<EFClientMessage>();
|
||||
}
|
||||
}
|
||||
|
||||
public ThreadSafeStatsService()
|
||||
{
|
||||
KillStatsSvc = new GenericRepository<EFClientKill>();
|
||||
ServerStatsSvc = new GenericRepository<EFServerStatistics>();
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ using SharedLibraryCore.Services;
|
||||
using IW4MAdmin.Plugins.Stats.Config;
|
||||
using IW4MAdmin.Plugins.Stats.Helpers;
|
||||
using IW4MAdmin.Plugins.Stats.Models;
|
||||
using SharedLibraryCore.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IW4MAdmin.Plugins.Stats
|
||||
{
|
||||
@ -122,8 +124,11 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
// meta data info
|
||||
async Task<List<ProfileMeta>> getStats(int clientId)
|
||||
{
|
||||
var statsSvc = new GenericRepository<EFClientStatistics>();
|
||||
var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId);
|
||||
IList<EFClientStatistics> clientStats;
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
clientStats = await ctx.Set<EFClientStatistics>().Where(c => c.ClientId == clientId).ToListAsync();
|
||||
}
|
||||
|
||||
int kills = clientStats.Sum(c => c.Kills);
|
||||
int deaths = clientStats.Sum(c => c.Deaths);
|
||||
@ -170,8 +175,14 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
|
||||
async Task<List<ProfileMeta>> getAnticheatInfo(int clientId)
|
||||
{
|
||||
var statsSvc = new GenericRepository<EFClientStatistics>();
|
||||
var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId);
|
||||
IList<EFClientStatistics> clientStats;
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
clientStats = await ctx.Set<EFClientStatistics>()
|
||||
.Include(c => c.HitLocations)
|
||||
.Where(c => c.ClientId == clientId)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
double headRatio = 0;
|
||||
double chestRatio = 0;
|
||||
@ -246,19 +257,24 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
|
||||
async Task<List<ProfileMeta>> getMessages(int clientId)
|
||||
{
|
||||
var messageSvc = new GenericRepository<EFClientMessage>();
|
||||
var messages = await messageSvc.FindAsync(m => m.ClientId == clientId);
|
||||
var messageMeta = messages.Select(m => new ProfileMeta()
|
||||
List<ProfileMeta> messageMeta;
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
Key = "EventMessage",
|
||||
Value = m.Message,
|
||||
When = m.TimeSent,
|
||||
Extra = m.ServerId.ToString()
|
||||
}).ToList();
|
||||
var messages = ctx.Set<EFClientMessage>().Where(m => m.ClientId == clientId);
|
||||
|
||||
messageMeta = await messages.Select(m => new ProfileMeta()
|
||||
{
|
||||
Key = "EventMessage",
|
||||
Value = m.Message,
|
||||
When = m.TimeSent,
|
||||
Extra = m.ServerId.ToString()
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
messageMeta.Add(new ProfileMeta()
|
||||
{
|
||||
Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
|
||||
Value = messages.Count
|
||||
Value = messageMeta.Count
|
||||
});
|
||||
|
||||
return messageMeta;
|
||||
@ -275,16 +291,20 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
|
||||
string totalKills(Server server)
|
||||
{
|
||||
var serverStats = new GenericRepository<EFServerStatistics>();
|
||||
return serverStats.Find(s => s.Active)
|
||||
.Sum(c => c.TotalKills).ToString("#,##0");
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
long kills = ctx.Set<EFServerStatistics>().Where(s => s.Active).Sum(s => s.TotalKills);
|
||||
return kills.ToString("#,##0");
|
||||
}
|
||||
}
|
||||
|
||||
string totalPlayTime(Server server)
|
||||
{
|
||||
var serverStats = new GenericRepository<EFServerStatistics>();
|
||||
return Math.Ceiling((serverStats.GetQuery(s => s.Active)
|
||||
.Sum(c => c.TotalPlayTime) / 3600.0)).ToString("#,##0");
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
long playTime = ctx.Set<EFServerStatistics>().Where(s => s.Active).Sum(s => s.TotalPlayTime);
|
||||
return (playTime / 3600.0).ToString("#,##0");
|
||||
}
|
||||
}
|
||||
|
||||
string topStats(Server s)
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.Plugins.Stats</PackageId>
|
||||
@ -26,7 +27,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
@ -22,7 +23,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -8,6 +8,8 @@ using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Services;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using System.Linq;
|
||||
using SharedLibraryCore.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IW4MAdmin.Plugins.Welcome
|
||||
{
|
||||
@ -88,8 +90,18 @@ namespace IW4MAdmin.Plugins.Welcome
|
||||
|
||||
if (newPlayer.Level == Player.Permission.Flagged)
|
||||
{
|
||||
var penalty = await new GenericRepository<EFPenalty>().FindAsync(p => p.OffenderId == newPlayer.ClientId && p.Type == Penalty.PenaltyType.Flag);
|
||||
E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7({penalty.FirstOrDefault()?.Offense}) has joined!");
|
||||
string penaltyReason;
|
||||
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
penaltyReason = await ctx.Penalties
|
||||
.Where(p => p.OffenderId == newPlayer.ClientId && p.Type == Penalty.PenaltyType.Flag)
|
||||
.OrderByDescending(p => p.When)
|
||||
.Select(p => p.AutomatedOffense ?? p.Offense)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7({penaltyReason}) has joined!");
|
||||
}
|
||||
else
|
||||
E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer));
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.Plugins.Welcome</PackageId>
|
||||
@ -25,7 +26,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
|
@ -68,7 +68,6 @@ namespace SharedLibraryCore
|
||||
|
||||
ScriptEngine.Execute(script);
|
||||
ScriptEngine.SetValue("_localization", Utilities.CurrentLocalization);
|
||||
ScriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient);
|
||||
dynamic pluginObject = ScriptEngine.GetValue("plugin").ToObject();
|
||||
|
||||
this.Author = pluginObject.author;
|
||||
@ -87,6 +86,7 @@ namespace SharedLibraryCore
|
||||
{
|
||||
ScriptEngine.SetValue("_gameEvent", E);
|
||||
ScriptEngine.SetValue("_server", S);
|
||||
ScriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(S));
|
||||
return Task.FromResult(ScriptEngine.Execute("plugin.onEventAsync(_gameEvent, _server)").GetCompletionValue());
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ namespace SharedLibraryCore
|
||||
Port = config.Port;
|
||||
Manager = mgr;
|
||||
Logger = Manager.GetLogger(this.GetHashCode());
|
||||
Logger.WriteInfo(this.ToString());
|
||||
ServerConfig = config;
|
||||
RemoteConnection = new RCon.Connection(IP, Port, Password, Logger);
|
||||
|
||||
@ -263,7 +264,7 @@ namespace SharedLibraryCore
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{IP}_{Port}";
|
||||
return $"{IP}-{Port}";
|
||||
}
|
||||
|
||||
protected async Task<bool> ScriptLoaded()
|
||||
|
@ -1,154 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedLibraryCore.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Services
|
||||
{
|
||||
// https://stackoverflow.com/questions/43677906/crud-operations-with-entityframework-using-generic-type
|
||||
public class GenericRepository<TEntity> where TEntity : class
|
||||
{
|
||||
private DatabaseContext _context;
|
||||
private DbSet<TEntity> _dbSet;
|
||||
private readonly bool ShouldTrack;
|
||||
|
||||
public GenericRepository(bool shouldTrack)
|
||||
{
|
||||
this.ShouldTrack = shouldTrack;
|
||||
}
|
||||
|
||||
public GenericRepository() { }
|
||||
|
||||
protected DbContext Context
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
_context = new DatabaseContext(!ShouldTrack);
|
||||
}
|
||||
|
||||
return _context;
|
||||
}
|
||||
}
|
||||
|
||||
protected DbSet<TEntity> DBSet
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dbSet == null)
|
||||
{
|
||||
_dbSet = this.Context.Set<TEntity>();
|
||||
}
|
||||
|
||||
return _dbSet;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task<IList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
|
||||
{
|
||||
return await this.GetQuery(predicate, orderExpression).ToListAsync();
|
||||
}
|
||||
|
||||
public virtual IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
|
||||
{
|
||||
return this.GetQuery(predicate, orderExpression).AsEnumerable();
|
||||
}
|
||||
|
||||
public virtual IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
|
||||
{
|
||||
IQueryable<TEntity> qry = this.DBSet;
|
||||
|
||||
foreach (var property in this.Context.Model.FindEntityType(typeof(TEntity)).GetNavigations())
|
||||
qry = qry.Include(property.Name);
|
||||
|
||||
|
||||
if (predicate != null)
|
||||
qry = qry.Where(predicate);
|
||||
|
||||
if (orderExpression != null)
|
||||
return orderExpression(qry);
|
||||
|
||||
|
||||
return qry;
|
||||
}
|
||||
|
||||
public virtual void Insert<T>(T entity) where T : class
|
||||
{
|
||||
DbSet<T> dbSet = this.Context.Set<T>();
|
||||
dbSet.Add(entity);
|
||||
}
|
||||
|
||||
public virtual TEntity Insert(TEntity entity)
|
||||
{
|
||||
return DBSet.Add(entity).Entity;
|
||||
}
|
||||
|
||||
public virtual void Update<T>(T entity) where T : class
|
||||
{
|
||||
DbSet<T> dbSet = this.Context.Set<T>();
|
||||
dbSet.Attach(entity);
|
||||
this.Context.Entry(entity).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public virtual void Update(TEntity entity)
|
||||
{
|
||||
this.Attach(entity);
|
||||
this.Context.Entry(entity).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public virtual void Delete<T>(T entity) where T : class
|
||||
{
|
||||
DbSet<T> dbSet = this.Context.Set<T>();
|
||||
|
||||
if (this.Context.Entry(entity).State == EntityState.Detached)
|
||||
dbSet.Attach(entity);
|
||||
|
||||
dbSet.Remove(entity);
|
||||
}
|
||||
|
||||
public virtual void Delete(TEntity entity)
|
||||
{
|
||||
if (this.Context.Entry(entity).State == EntityState.Detached)
|
||||
this.Attach(entity);
|
||||
|
||||
this.DBSet.Remove(entity);
|
||||
|
||||
}
|
||||
|
||||
public virtual void Delete<T>(object[] id) where T : class
|
||||
{
|
||||
DbSet<T> dbSet = this.Context.Set<T>();
|
||||
T entity = dbSet.Find(id);
|
||||
dbSet.Attach(entity);
|
||||
dbSet.Remove(entity);
|
||||
}
|
||||
|
||||
public virtual void Delete(object id)
|
||||
{
|
||||
TEntity entity = this.DBSet.Find(id);
|
||||
this.Delete(entity);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Attach(TEntity entity)
|
||||
{
|
||||
if (this.Context.Entry(entity).State == EntityState.Detached)
|
||||
this.DBSet.Attach(entity);
|
||||
}
|
||||
|
||||
public virtual void SaveChanges()
|
||||
{
|
||||
this.Context.SaveChanges();
|
||||
}
|
||||
|
||||
public virtual Task SaveChangesAsync()
|
||||
{
|
||||
return this.Context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.SharedLibraryCore</PackageId>
|
||||
@ -12,15 +13,6 @@
|
||||
<Configurations>Debug;Release;Prerelease</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Migrations\20180502195240_Update.cs" />
|
||||
<Compile Remove="Migrations\20180923025324_FixForPostgreSQL.cs" />
|
||||
<Compile Remove="Migrations\20180923025702_FixForPostgreSQL.cs" />
|
||||
<Compile Remove="Migrations\20180923030248_FixForPostgreSQL.cs" />
|
||||
<Compile Remove="Migrations\20180923030426_FixForPostgreSQL.cs" />
|
||||
<Compile Remove="Migrations\20180923030528_FixForPostgreSQL.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Jint" Version="2.11.58" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.4" />
|
||||
@ -39,7 +31,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
|
@ -27,7 +27,7 @@ namespace SharedLibraryCore
|
||||
#endif
|
||||
public static Encoding EncodingType;
|
||||
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary<string, string>());
|
||||
public static Player IW4MAdminClient = new Player() { ClientId = 1, Level = Player.Permission.Console };
|
||||
public static Player IW4MAdminClient(Server server = null) => new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = server };
|
||||
|
||||
public static string HttpRequest(string location, string header, string headerValue)
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Database;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Services;
|
||||
@ -33,8 +35,14 @@ namespace WebfrontCore.Controllers
|
||||
|
||||
public async Task<IActionResult> PublicAsync()
|
||||
{
|
||||
var penalties = await (new GenericRepository<EFPenalty>())
|
||||
.FindAsync(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active);
|
||||
IList<EFPenalty> penalties;
|
||||
|
||||
using (var ctx = new DatabaseContext(disableTracking: true))
|
||||
{
|
||||
penalties = await ctx.Penalties
|
||||
.Where(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<RazorCompileOnBuild>false</RazorCompileOnBuild>
|
||||
<RazorCompileOnPublish>false</RazorCompileOnPublish>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
@ -63,7 +64,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" />
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.1.5" />
|
||||
<PackageReference Update="Microsoft.AspNetCore" Version="2.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user