diff --git a/Application/Application.csproj b/Application/Application.csproj
index 9d9c84940..d06635524 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -5,7 +5,7 @@
netcoreapp2.1
false
RaidMax.IW4MAdmin.Application
- 2.1.8
+ 2.1.9
RaidMax
Forever None
IW4MAdmin
@@ -80,15 +80,17 @@
-
+
-
+
+
+
+
-
+
-
diff --git a/Application/BuildScripts/PostBuild.bat b/Application/BuildScripts/PostBuild.bat
index 98932ef91..db0ed34ae 100644
--- a/Application/BuildScripts/PostBuild.bat
+++ b/Application/BuildScripts/PostBuild.bat
@@ -2,6 +2,9 @@ set SolutionDir=%1
set ProjectDir=%2
set TargetDir=%3
set OutDir=%4
+set Version=%5
+
+echo %Version% > "%SolutionDir%DEPLOY\version.txt"
echo Copying dependency configs
copy "%SolutionDir%WebfrontCore\%OutDir%*.deps.json" "%TargetDir%"
diff --git a/Application/GameEventHandler.cs b/Application/GameEventHandler.cs
index 0a4c00ec3..dceb1b326 100644
--- a/Application/GameEventHandler.cs
+++ b/Application/GameEventHandler.cs
@@ -18,20 +18,23 @@ namespace IW4MAdmin.Application
{
Manager = mgr;
OutOfOrderEvents = new SortedList();
- IsProcessingEvent = new SemaphoreSlim(0);
- IsProcessingEvent.Release();
+ IsProcessingEvent = new SemaphoreSlim(2, 2);
}
public void AddEvent(GameEvent gameEvent)
{
+ IsProcessingEvent.Wait();
((Manager as ApplicationManager).OnServerEvent)(this, new GameEventArgs(null, false, gameEvent));
if (gameEvent.Type == GameEvent.EventType.Connect)
{
+ IsProcessingEvent.Wait();
if (!gameEvent.OnProcessed.Wait(30 * 1000))
{
Manager.GetLogger().WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_TIMEOUT"]} [{gameEvent.Id}, {gameEvent.Type}]");
}
+ IsProcessingEvent.Release(1);
}
+ IsProcessingEvent.Release(1);
return;
#if DEBUG
diff --git a/Application/Properties/PublishProfiles/Stable-Windows.pubxml b/Application/Properties/PublishProfiles/Stable-Windows.pubxml
deleted file mode 100644
index 49599c2f4..000000000
--- a/Application/Properties/PublishProfiles/Stable-Windows.pubxml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- FileSystem
- Release
- netcoreapp2.0
- C:\Projects\IW4M-Admin\Publish\Windows
-
-
\ No newline at end of file
diff --git a/Application/Server.cs b/Application/Server.cs
index 0fb40c348..905e88740 100644
--- a/Application/Server.cs
+++ b/Application/Server.cs
@@ -231,7 +231,14 @@ namespace IW4MAdmin
// reban the "evading" guid
if (player.Level != Player.Permission.Banned && currentBan.Type == Penalty.PenaltyType.Ban)
+ {
+ // hack: re apply the automated offense to the reban
+ if (currentBan.AutomatedOffense != null)
+ {
+ autoKickClient.AdministeredPenalties.Add(new EFPenalty() { AutomatedOffense = currentBan.AutomatedOffense });
+ }
await player.Ban($"{currentBan.Offense}", autoKickClient);
+ }
// they didn't fully connect so empty their slot
Players[player.ClientNumber] = null;
diff --git a/DiscordWebhook/DiscordWebhook.pyproj b/DiscordWebhook/DiscordWebhook.pyproj
index f8020fba8..c3ed35f4f 100644
--- a/DiscordWebhook/DiscordWebhook.pyproj
+++ b/DiscordWebhook/DiscordWebhook.pyproj
@@ -10,6 +10,7 @@
.
.
DiscordWebhook
+ true
DiscordWebhook
MSBuild|env|$(MSBuildProjectFullPath)
False
@@ -49,7 +50,7 @@
True
-
+
@@ -58,4 +59,37 @@
+
+
+
+
+ True
+ True
+ http://localhost
+ False
+
+
+
+
+
+
+ CurrentPage
+ True
+ False
+ False
+ False
+
+
+
+
+
+
+
+
+ False
+ False
+
+
+
+
\ No newline at end of file
diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln
index 319250726..efe8e8387 100644
--- a/IW4MAdmin.sln
+++ b/IW4MAdmin.sln
@@ -10,6 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
_commands.gsc = _commands.gsc
_customcallbacks.gsc = _customcallbacks.gsc
README.md = README.md
+ RunPublishPre.cmd = RunPublishPre.cmd
version.txt = version.txt
EndProjectSection
EndProject
diff --git a/RunPublishPre.cmd b/RunPublishPre.cmd
new file mode 100644
index 000000000..b9954b86d
--- /dev/null
+++ b/RunPublishPre.cmd
@@ -0,0 +1,8 @@
+dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease
+dotnet publish Application/Application.csproj -c Prerelease -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease
+dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease\GameLogServer
+call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat"
+msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\GameLogServer\
+msbuild DiscordWebhook/DiscordWebhook.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\DiscordWebhook\
+cd "C:\Projects\IW4M-Admin\DEPLOY\"
+PowerShell ".\upload_prerelease.ps1"
\ No newline at end of file
diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs
index 7951080c7..323c89531 100644
--- a/SharedLibraryCore/Commands/NativeCommands.cs
+++ b/SharedLibraryCore/Commands/NativeCommands.cs
@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
+using SharedLibraryCore.Events;
using SharedLibraryCore.Objects;
using SharedLibraryCore.Services;
using System;
@@ -464,6 +465,7 @@ namespace SharedLibraryCore.Commands
return;
}
+ Player.Permission oldPerm = E.Target.Level;
Player.Permission newPerm = Utilities.MatchPermission(E.Data);
if (newPerm == Player.Permission.Owner &&
@@ -518,6 +520,21 @@ namespace SharedLibraryCore.Commands
E.Owner.Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
}
+ var e = new GameEvent()
+ {
+ Origin = E.Origin,
+ Target = E.Target,
+ Owner = E.Owner,
+ Type = GameEvent.EventType.ChangePermission,
+ Extra = new Change()
+ {
+ PreviousValue = oldPerm.ToString(),
+ NewValue = newPerm.ToString()
+ }
+ };
+
+ E.Owner.Manager.GetEventHandler().AddEvent(e);
+
await E.Origin.Tell($"{E.Target.Name} {Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS"]}");
}
diff --git a/SharedLibraryCore/Database/Models/EFChangeHistory.cs b/SharedLibraryCore/Database/Models/EFChangeHistory.cs
index 0fc9794ab..33be8cf50 100644
--- a/SharedLibraryCore/Database/Models/EFChangeHistory.cs
+++ b/SharedLibraryCore/Database/Models/EFChangeHistory.cs
@@ -12,7 +12,8 @@ namespace SharedLibraryCore.Database.Models
{
public enum ChangeType
{
- Permission
+ Permission,
+ Ban
}
[Key]
@@ -23,5 +24,7 @@ namespace SharedLibraryCore.Database.Models
public DateTime TimeChanged { get; set; } = DateTime.UtcNow;
[MaxLength(128)]
public string Comment { get; set; }
+ public string PreviousValue { get; set; }
+ public string CurrentValue { get; set; }
}
}
diff --git a/SharedLibraryCore/Database/Models/SharedEntity.cs b/SharedLibraryCore/Database/Models/SharedEntity.cs
index 7784cbcaf..269158546 100644
--- a/SharedLibraryCore/Database/Models/SharedEntity.cs
+++ b/SharedLibraryCore/Database/Models/SharedEntity.cs
@@ -8,6 +8,6 @@ namespace SharedLibraryCore.Database.Models
{
public class SharedEntity
{
- public bool Active { get; set; }
+ public bool Active { get; set; } = true;
}
}
diff --git a/SharedLibraryCore/Events/Change.cs b/SharedLibraryCore/Events/Change.cs
new file mode 100644
index 000000000..6e4eaea12
--- /dev/null
+++ b/SharedLibraryCore/Events/Change.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharedLibraryCore.Events
+{
+ ///
+ /// represents change from one value to another
+ ///
+ class Change
+ {
+ ///
+ /// represents the previous value of the item
+ ///
+ public string PreviousValue { get; set; }
+ ///
+ /// represents the new/current value of the item
+ ///
+ public string NewValue { get; set; }
+ }
+}
diff --git a/SharedLibraryCore/Events/EventAPI.cs b/SharedLibraryCore/Events/EventAPI.cs
index 4fc37e5e2..a8fbac192 100644
--- a/SharedLibraryCore/Events/EventAPI.cs
+++ b/SharedLibraryCore/Events/EventAPI.cs
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
+using SharedLibraryCore.Database;
+using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
namespace SharedLibraryCore.Events
@@ -22,7 +25,92 @@ namespace SharedLibraryCore.Events
return eventList;
}
- public static void OnGameEvent(object sender, GameEventArgs eventState)
+ private static async Task SaveChangeHistory(GameEvent e)
+ {
+ EFChangeHistory change = null;
+
+ switch (e.Type)
+ {
+ case GameEvent.EventType.Unknown:
+ break;
+ case GameEvent.EventType.Start:
+ break;
+ case GameEvent.EventType.Stop:
+ break;
+ case GameEvent.EventType.Connect:
+ break;
+ case GameEvent.EventType.Join:
+ break;
+ case GameEvent.EventType.Quit:
+ break;
+ case GameEvent.EventType.Disconnect:
+ break;
+ case GameEvent.EventType.MapEnd:
+ break;
+ case GameEvent.EventType.MapChange:
+ break;
+ case GameEvent.EventType.Say:
+ break;
+ case GameEvent.EventType.Warn:
+ break;
+ case GameEvent.EventType.Report:
+ break;
+ case GameEvent.EventType.Flag:
+ break;
+ case GameEvent.EventType.Unflag:
+ break;
+ case GameEvent.EventType.Kick:
+ break;
+ case GameEvent.EventType.TempBan:
+ break;
+ case GameEvent.EventType.Ban:
+ change = new EFChangeHistory()
+ {
+ OriginEntityId = e.Origin.ClientId,
+ TargetEntityId = e.Target.ClientId,
+ TypeOfChange = EFChangeHistory.ChangeType.Ban,
+ Comment = e.Data
+ };
+ break;
+ case GameEvent.EventType.Command:
+ break;
+ case GameEvent.EventType.ChangePermission:
+ change = new EFChangeHistory()
+ {
+ OriginEntityId = e.Origin.ClientId,
+ TargetEntityId = e.Target.ClientId,
+ TypeOfChange = EFChangeHistory.ChangeType.Permission,
+ PreviousValue = ((Change)e.Extra).PreviousValue,
+ CurrentValue = ((Change)e.Extra).NewValue
+ };
+ break;
+ case GameEvent.EventType.Broadcast:
+ break;
+ case GameEvent.EventType.Tell:
+ break;
+ case GameEvent.EventType.ScriptDamage:
+ break;
+ case GameEvent.EventType.ScriptKill:
+ break;
+ case GameEvent.EventType.Damage:
+ break;
+ case GameEvent.EventType.Kill:
+ break;
+ case GameEvent.EventType.JoinTeam:
+ break;
+ }
+
+ if (change != null)
+ {
+ using (var ctx = new DatabaseContext(true))
+ {
+ ctx.EFChangeHistory.Add(change);
+ await ctx.SaveChangesAsync();
+ }
+ }
+ }
+
+ public static async void OnGameEvent(object sender, GameEventArgs eventState)
{
var E = eventState.Event;
// don't want to clog up the api with unknown events
@@ -62,6 +150,8 @@ namespace SharedLibraryCore.Events
// add the new event to the list
AddNewEvent(apiEvent);
+
+ await SaveChangeHistory(E);
}
///
diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs
index 59be67b38..1bde1db78 100644
--- a/SharedLibraryCore/Events/GameEvent.cs
+++ b/SharedLibraryCore/Events/GameEvent.cs
@@ -9,41 +9,118 @@ namespace SharedLibraryCore
{
public enum EventType
{
+ ///
+ /// the event wasn't parsed properly
+ ///
Unknown,
// events "generated" by the server
+ ///
+ /// a server started being monitored
+ ///
Start,
+ ///
+ /// a server stopped being monitored
+ ///
Stop,
+ ///
+ /// a client was detecting as connecting via RCon
+ ///
Connect,
+ ///
+ /// a client was detecting joining via log
+ ///
Join,
+ ///
+ /// a client was detected leaving via log
+ ///
Quit,
+ ///
+ /// a client was detected leaving by RCon
+ ///
Disconnect,
+ ///
+ /// the current map ended
+ ///
MapEnd,
+ ///
+ /// the current map changed
+ ///
MapChange,
- // events "generated" by clients
+ // events "generated" by clients
+ ///
+ /// a client sent a message
+ ///
Say,
+ ///
+ /// a client was warned
+ ///
Warn,
+ ///
+ /// a client was reported
+ ///
Report,
+ ///
+ /// a client was flagged
+ ///
Flag,
+ ///
+ /// a client was unflagged
+ ///
Unflag,
+ ///
+ /// a client was kicked
+ ///
Kick,
+ ///
+ /// a client was tempbanned
+ ///
TempBan,
+ ///
+ /// a client was banned
+ ///
Ban,
+ ///
+ /// a client entered a command
+ ///
Command,
+ ///
+ /// a client's permission was changed
+ ///
+ ChangePermission,
// events "generated" by IW4MAdmin
+ ///
+ /// a message is sent to all clients
+ ///
Broadcast,
+ ///
+ /// a message is sent to a specific client
+ ///
Tell,
// events "generated" by script/log
+ ///
+ /// AC Damage Log
+ ///
ScriptDamage,
+ ///
+ /// AC Kill Log
+ ///
ScriptKill,
+ ///
+ /// damage info printed out by game script
+ ///
Damage,
+ ///
+ /// kill info printed out by game script
+ ///
Kill,
+ ///
+ /// team info printed out by game script
+ ///
JoinTeam,
-
- StatusUpdate
}
static long NextEventId;
diff --git a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs b/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs
index c38024983..362b51317 100644
--- a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs
+++ b/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs
@@ -6,7 +6,15 @@ namespace SharedLibraryCore.Migrations
{
protected override void Up(MigrationBuilder migrationBuilder)
{
-
+ // hack: we can't alter the column on SQLite, but we need max length limit for the Index in MySQL etc
+ if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite")
+ {
+ migrationBuilder.AlterColumn(
+ name: "Name",
+ table: "EFAlias",
+ maxLength: 24,
+ nullable: false);
+ }
}
protected override void Down(MigrationBuilder migrationBuilder)
diff --git a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs
new file mode 100644
index 000000000..4db53a4f1
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs
@@ -0,0 +1,684 @@
+//
+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("20180912015012_AddPreviousCurrentValueToEFChangeHistory")]
+ partial class AddPreviousCurrentValueToEFChangeHistory
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.1.2-rtm-30932");
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
+ {
+ b.Property("SnapshotId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("CurrentSessionLength");
+
+ b.Property("CurrentStrain");
+
+ b.Property("CurrentViewAngleVector3Id");
+
+ b.Property("Deaths");
+
+ b.Property("Distance");
+
+ b.Property("EloRating");
+
+ b.Property("HitDestinationVector3Id");
+
+ b.Property("HitLocation");
+
+ b.Property("HitOriginVector3Id");
+
+ b.Property("HitType");
+
+ b.Property("Hits");
+
+ b.Property("Kills");
+
+ b.Property("LastStrainAngleVector3Id");
+
+ b.Property("SessionAngleOffset");
+
+ b.Property("SessionSPM");
+
+ b.Property("SessionScore");
+
+ b.Property("StrainAngleBetween");
+
+ b.Property("TimeSinceLastEvent");
+
+ b.Property("WeaponId");
+
+ b.Property("When");
+
+ b.HasKey("SnapshotId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("CurrentViewAngleVector3Id");
+
+ b.HasIndex("HitDestinationVector3Id");
+
+ b.HasIndex("HitOriginVector3Id");
+
+ b.HasIndex("LastStrainAngleVector3Id");
+
+ b.ToTable("EFACSnapshot");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
+ {
+ b.Property("KillId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AttackerId");
+
+ b.Property("Damage");
+
+ b.Property("DeathOriginVector3Id");
+
+ b.Property("DeathType");
+
+ b.Property("Fraction");
+
+ b.Property("HitLoc");
+
+ b.Property("IsKill");
+
+ b.Property("KillOriginVector3Id");
+
+ b.Property("Map");
+
+ b.Property("ServerId");
+
+ b.Property("VictimId");
+
+ b.Property("ViewAnglesVector3Id");
+
+ b.Property("VisibilityPercentage");
+
+ b.Property("Weapon");
+
+ b.Property("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("MessageId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("Message");
+
+ b.Property("ServerId");
+
+ b.Property("TimeSent");
+
+ b.HasKey("MessageId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFClientMessages");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
+ {
+ b.Property("RatingHistoryId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.HasKey("RatingHistoryId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("EFClientRatingHistory");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
+ {
+ b.Property("ClientId");
+
+ b.Property("ServerId");
+
+ b.Property("Active");
+
+ b.Property("Deaths");
+
+ b.Property("EloRating");
+
+ b.Property("Kills");
+
+ b.Property("MaxStrain");
+
+ b.Property("RollingWeightedKDR");
+
+ b.Property("SPM");
+
+ b.Property("Skill");
+
+ b.Property("TimePlayed");
+
+ b.Property("VisionAverage");
+
+ b.HasKey("ClientId", "ServerId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFClientStatistics");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
+ {
+ b.Property("HitLocationCountId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId")
+ .HasColumnName("EFClientStatistics_ClientId");
+
+ b.Property("HitCount");
+
+ b.Property("HitOffsetAverage");
+
+ b.Property("Location");
+
+ b.Property("MaxAngleDistance");
+
+ b.Property("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("RatingId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ActivityAmount");
+
+ b.Property("Newest");
+
+ b.Property("Performance");
+
+ b.Property("Ranking");
+
+ b.Property("RatingHistoryId");
+
+ b.Property("ServerId");
+
+ b.Property("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("ServerId");
+
+ b.Property("Active");
+
+ b.Property("Port");
+
+ b.HasKey("ServerId");
+
+ b.ToTable("EFServers");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
+ {
+ b.Property("StatisticId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ServerId");
+
+ b.Property("TotalKills");
+
+ b.Property("TotalPlayTime");
+
+ b.HasKey("StatisticId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFServerStatistics");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
+ {
+ b.Property("AliasId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("DateAdded");
+
+ b.Property("IPAddress");
+
+ b.Property("LinkId");
+
+ b.Property("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("AliasLinkId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.HasKey("AliasLinkId");
+
+ b.ToTable("EFAliasLinks");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
+ {
+ b.Property("ChangeHistoryId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("Comment")
+ .HasMaxLength(128);
+
+ b.Property("CurrentValue");
+
+ b.Property("OriginEntityId");
+
+ b.Property("PreviousValue");
+
+ b.Property("TargetEntityId");
+
+ b.Property("TimeChanged");
+
+ b.Property("TypeOfChange");
+
+ b.HasKey("ChangeHistoryId");
+
+ b.ToTable("EFChangeHistory");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AliasLinkId");
+
+ b.Property("Connections");
+
+ b.Property("CurrentAliasId");
+
+ b.Property("FirstConnection");
+
+ b.Property("LastConnection");
+
+ b.Property("Level");
+
+ b.Property("Masked");
+
+ b.Property("NetworkId");
+
+ b.Property("Password");
+
+ b.Property("PasswordSalt");
+
+ b.Property("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("MetaId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("Created");
+
+ b.Property("Extra");
+
+ b.Property("Key")
+ .IsRequired();
+
+ b.Property("Updated");
+
+ b.Property("Value")
+ .IsRequired();
+
+ b.HasKey("MetaId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("EFMeta");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
+ {
+ b.Property("PenaltyId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AutomatedOffense");
+
+ b.Property("Expires");
+
+ b.Property("LinkId");
+
+ b.Property("OffenderId");
+
+ b.Property("Offense")
+ .IsRequired();
+
+ b.Property("PunisherId");
+
+ b.Property("Type");
+
+ b.Property("When");
+
+ b.HasKey("PenaltyId");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("OffenderId");
+
+ b.HasIndex("PunisherId");
+
+ b.ToTable("EFPenalties");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
+ {
+ b.Property("Vector3Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("EFACSnapshotSnapshotId");
+
+ b.Property("X");
+
+ b.Property("Y");
+
+ b.Property("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("CurrentViewAngleVector3Id");
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
+ .WithMany()
+ .HasForeignKey("HitDestinationVector3Id");
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
+ .WithMany()
+ .HasForeignKey("HitOriginVector3Id");
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
+ .WithMany()
+ .HasForeignKey("LastStrainAngleVector3Id");
+ });
+
+ 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
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs
new file mode 100644
index 000000000..2ccf0c2a9
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs
@@ -0,0 +1,31 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace SharedLibraryCore.Migrations
+{
+ public partial class AddPreviousCurrentValueToEFChangeHistory : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "CurrentValue",
+ table: "EFChangeHistory",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "PreviousValue",
+ table: "EFChangeHistory",
+ nullable: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "CurrentValue",
+ table: "EFChangeHistory");
+
+ migrationBuilder.DropColumn(
+ name: "PreviousValue",
+ table: "EFChangeHistory");
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
index d1f923a98..9e579405d 100644
--- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
+++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
@@ -356,8 +356,12 @@ namespace SharedLibraryCore.Migrations
b.Property("Comment")
.HasMaxLength(128);
+ b.Property("CurrentValue");
+
b.Property("OriginEntityId");
+ b.Property("PreviousValue");
+
b.Property("TargetEntityId");
b.Property("TimeChanged");
diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs
index 13a997242..2e0177ce0 100644
--- a/SharedLibraryCore/Services/PenaltyService.cs
+++ b/SharedLibraryCore/Services/PenaltyService.cs
@@ -101,9 +101,8 @@ namespace SharedLibraryCore.Services
public async Task> GetRecentPenalties(int count, int offset, Penalty.PenaltyType showOnly = Penalty.PenaltyType.Any)
{
- using (var context = new DatabaseContext())
+ using (var context = new DatabaseContext(true))
return await context.Penalties
- .AsNoTracking()
.Include(p => p.Offender.CurrentAlias)
.Include(p => p.Punisher.CurrentAlias)
.Where(p => showOnly == Penalty.PenaltyType.Any ? p.Type != Penalty.PenaltyType.Any : p.Type == showOnly)
@@ -116,9 +115,8 @@ namespace SharedLibraryCore.Services
public async Task> GetClientPenaltiesAsync(int clientId)
{
- using (var context = new DatabaseContext())
+ using (var context = new DatabaseContext(true))
return await context.Penalties
- .AsNoTracking()
.Where(p => p.OffenderId == clientId)
.Where(p => p.Active)
.Include(p => p.Offender.CurrentAlias)
@@ -134,10 +132,9 @@ namespace SharedLibraryCore.Services
///
public async Task> ReadGetClientPenaltiesAsync(int clientId, bool victim = true)
{
- using (var context = new DatabaseContext())
+ using (var context = new DatabaseContext(true))
{
- context.ChangeTracker.AutoDetectChangesEnabled = false;
- context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ // todo: clean this up
if (victim)
{
var now = DateTime.UtcNow;
@@ -233,32 +230,26 @@ namespace SharedLibraryCore.Services
}
}
- public async Task> GetActivePenaltiesAsync(int aliasId, int ip = 0)
+ public async Task> GetActivePenaltiesAsync(int linkId, int ip = 0)
{
var now = DateTime.UtcNow;
- using (var context = new DatabaseContext())
+ using (var context = new DatabaseContext(true))
{
- var iqPenalties = await (from link in context.AliasLinks
- where link.AliasLinkId == aliasId
- join penalty in context.Penalties
- on link.AliasLinkId equals penalty.LinkId
- where penalty.Active
- where penalty.Expires > now
- orderby penalty.When descending
- select penalty).ToListAsync();
- if (ip != 0)
- {
- iqPenalties.AddRange(await (from alias in context.Aliases
- where alias.IPAddress == ip
- join penalty in context.Penalties
- on alias.LinkId equals penalty.LinkId
- where penalty.Active
- where penalty.Expires > now
- orderby penalty.When descending
- select penalty).ToListAsync());
- }
- return iqPenalties;
+ var iqPenalties = context.Penalties
+ .Where(p => p.LinkId == linkId ||
+ p.Link.Children.Any(a => a.IPAddress == ip))
+ .Where(p => p.Active)
+ .Where(p => p.Expires > now);
+
+
+#if DEBUG == true
+ var penaltiesSql = iqPenalties.ToSql();
+#endif
+
+ var activePenalties = await iqPenalties.ToListAsync();
+ // this is a bit more performant in memory (ordering)
+ return activePenalties.OrderByDescending(p =>p.When).ToList();
}
}
@@ -286,8 +277,6 @@ namespace SharedLibraryCore.Services
.ForEachAsync(c => c.Level = Player.Permission.User);
await internalContext.SaveChangesAsync();
}
-
-
}
});
diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj
index 04068ecf5..3522e9b87 100644
--- a/SharedLibraryCore/SharedLibraryCore.csproj
+++ b/SharedLibraryCore/SharedLibraryCore.csproj
@@ -36,7 +36,7 @@
-
+