Added additional properties method to allow easier extension to client properties
updated VPN plugin to use WebClient message is sent to client trying to execute commands before they are authenticated fixed rare issue with ToAdmins failing record bullet distance fraction for client kills (_customcallbacks) change client level/permissions through webfront ability to tempban through webfront
This commit is contained in:
parent
cc7628d058
commit
e77ef69ee8
@ -18,3 +18,7 @@ echo Copying plugins for publish
|
||||
del %SolutionDir%BUILD\Plugins\Tests.dll
|
||||
xcopy /Y "%SolutionDir%BUILD\Plugins" "%SolutionDir%Publish\Windows\Plugins\"
|
||||
xcopy /Y "%SolutionDir%BUILD\Plugins" "%SolutionDir%Publish\WindowsPrerelease\Plugins\"
|
||||
|
||||
echo Copying script plugins for publish
|
||||
xcopy /Y "%SolutionDir%Plugins\ScriptPlugins" "%SolutionDir%Publish\Windows\Plugins\"
|
||||
xcopy /Y "%SolutionDir%Plugins\ScriptPlugins" "%SolutionDir%Publish\WindowsPrerelease\Plugins\"
|
@ -78,6 +78,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
Type = GameEvent.EventType.Kill,
|
||||
Data = logLine,
|
||||
Origin = origin,
|
||||
Target = target,
|
||||
Owner = server
|
||||
};
|
||||
}
|
||||
@ -115,6 +116,8 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
|
||||
// damage
|
||||
if (eventType == "D")
|
||||
{
|
||||
if (!server.CustomCallback)
|
||||
{
|
||||
if (Regex.Match(eventType, @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$").Success)
|
||||
{
|
||||
@ -131,6 +134,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// join
|
||||
if (eventType == "J")
|
||||
|
@ -27,56 +27,54 @@ namespace IW4MAdmin.Application
|
||||
#if DEBUG
|
||||
Manager.GetLogger().WriteDebug($"Got new event of type {gameEvent.Type} for {gameEvent.Owner} with id {gameEvent.Id}");
|
||||
#endif
|
||||
GameEvent sortedEvent = null;
|
||||
lock (OutOfOrderEvents)
|
||||
{
|
||||
sortedEvent = OutOfOrderEvents.Values.FirstOrDefault();
|
||||
}
|
||||
// GameEvent sortedEvent = null;
|
||||
// lock (OutOfOrderEvents)
|
||||
// {
|
||||
// sortedEvent = OutOfOrderEvents.Values.FirstOrDefault();
|
||||
|
||||
while (sortedEvent?.Id == Interlocked.Read(ref NextEventId))
|
||||
{
|
||||
lock (OutOfOrderEvents)
|
||||
{
|
||||
OutOfOrderEvents.RemoveAt(0);
|
||||
}
|
||||
AddEvent(sortedEvent);
|
||||
// while (sortedEvent?.Id == Interlocked.Read(ref NextEventId))
|
||||
// {
|
||||
// if (OutOfOrderEvents.Count > 0)
|
||||
// {
|
||||
// OutOfOrderEvents.RemoveAt(0);
|
||||
// }
|
||||
|
||||
lock (OutOfOrderEvents)
|
||||
{
|
||||
sortedEvent = OutOfOrderEvents.Values.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
// AddEvent(sortedEvent);
|
||||
// sortedEvent = OutOfOrderEvents.Values.FirstOrDefault();
|
||||
// }
|
||||
// }
|
||||
|
||||
// both the gameEvent Id and the LastEventId are thread safe because we want to synchronize when the
|
||||
// event occurs
|
||||
if (gameEvent.Id == Interlocked.Read(ref NextEventId))
|
||||
{
|
||||
#if DEBUG == true
|
||||
Manager.GetLogger().WriteDebug($"sent event with id {gameEvent.Id} to be processed");
|
||||
#endif
|
||||
// // both the gameEvent Id and the LastEventId are thread safe because we want to synchronize when the
|
||||
// // event occurs
|
||||
// if (gameEvent.Id == Interlocked.Read(ref NextEventId))
|
||||
// {
|
||||
//#if DEBUG == true
|
||||
// Manager.GetLogger().WriteDebug($"sent event with id {gameEvent.Id} to be processed");
|
||||
//#endif
|
||||
((Manager as ApplicationManager).OnServerEvent)(this, new GameEventArgs(null, false, gameEvent));
|
||||
Interlocked.Increment(ref NextEventId);
|
||||
}
|
||||
|
||||
// a "newer" event has been added before and "older" one has been added (due to threads and context switching)
|
||||
// so me must wait until the next expected one arrives
|
||||
else
|
||||
{
|
||||
#if DEBUG == true
|
||||
Manager.GetLogger().WriteWarning("Incoming event is out of order");
|
||||
Manager.GetLogger().WriteDebug($"Expected event Id is {Interlocked.Read(ref NextEventId)}, but got {gameEvent.Id} instead");
|
||||
#endif
|
||||
|
||||
// this prevents multiple threads from adding simultaneously
|
||||
lock (OutOfOrderEvents)
|
||||
{
|
||||
if (!OutOfOrderEvents.TryGetValue(gameEvent.Id, out GameEvent discard))
|
||||
{
|
||||
OutOfOrderEvents.Add(gameEvent.Id, gameEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
// Interlocked.Increment(ref NextEventId);
|
||||
// }
|
||||
|
||||
// // a "newer" event has been added before and "older" one has been added (due to threads and context switching)
|
||||
// // so me must wait until the next expected one arrives
|
||||
// else
|
||||
// {
|
||||
//#if DEBUG == true
|
||||
// Manager.GetLogger().WriteWarning("Incoming event is out of order");
|
||||
// Manager.GetLogger().WriteDebug($"Expected event Id is {Interlocked.Read(ref NextEventId)}, but got {gameEvent.Id} instead");
|
||||
//#endif
|
||||
|
||||
// // this prevents multiple threads from adding simultaneously
|
||||
// lock (OutOfOrderEvents)
|
||||
// {
|
||||
// if (!OutOfOrderEvents.TryGetValue(gameEvent.Id, out GameEvent discard))
|
||||
// {
|
||||
// OutOfOrderEvents.Add(gameEvent.Id, gameEvent);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ namespace IW4MAdmin.Application
|
||||
Localization.Configure.Initialize(ServerManager.GetApplicationSettings().Configuration()?.CustomLocale);
|
||||
loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
|
||||
ServerManager.Logger.WriteInfo($"Version is {Version}");
|
||||
|
||||
var api = API.Master.Endpoint.Get();
|
||||
|
||||
var version = new API.Master.VersionInfo()
|
||||
|
@ -81,6 +81,11 @@ namespace IW4MAdmin.Application
|
||||
if (GameEvent.ShouldOriginEventBeDelayed(newEvent))
|
||||
{
|
||||
Logger.WriteDebug($"Delaying origin execution of event type {newEvent.Type} for {newEvent.Origin} because they are not authed");
|
||||
if (newEvent.Type == GameEvent.EventType.Command)
|
||||
{
|
||||
await newEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_DELAYED_EVENT_WAIT"]);
|
||||
}
|
||||
|
||||
// offload it to the player to keep
|
||||
newEvent.Origin.DelayedEvents.Enqueue(newEvent);
|
||||
return;
|
||||
@ -104,7 +109,7 @@ namespace IW4MAdmin.Application
|
||||
var events = newEvent.Origin.DelayedEvents;
|
||||
|
||||
// add the delayed event to the queue
|
||||
while(events.Count > 0)
|
||||
while (events.Count > 0)
|
||||
{
|
||||
var oldEvent = events.Dequeue();
|
||||
|
||||
|
@ -19,7 +19,6 @@ using SharedLibraryCore.Localization;
|
||||
using IW4MAdmin.Application.RconParsers;
|
||||
using IW4MAdmin.Application.EventParsers;
|
||||
using IW4MAdmin.Application.IO;
|
||||
using IW4MAdmin.Application.Core;
|
||||
|
||||
namespace IW4MAdmin
|
||||
{
|
||||
@ -300,40 +299,6 @@ namespace IW4MAdmin
|
||||
}
|
||||
}
|
||||
|
||||
//// this allows us to catch exceptions but still run it parallel
|
||||
//async Task pluginHandlingAsync(Task onEvent, string pluginName)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// await onEvent;
|
||||
// }
|
||||
|
||||
// // this happens if a plugin (login) wants to stop commands from executing
|
||||
// catch (AuthorizationException e)
|
||||
// {
|
||||
// await E.Origin.Tell($"{loc["COMMAND_NOTAUTHORIZED"]} - {e.Message}");
|
||||
// canExecuteCommand = false;
|
||||
// }
|
||||
|
||||
// catch (Exception Except)
|
||||
// {
|
||||
// Logger.WriteError($"{loc["SERVER_PLUGIN_ERROR"]} [{pluginName}]");
|
||||
// Logger.WriteDebug(String.Format("Error Message: {0}", Except.Message));
|
||||
// Logger.WriteDebug(String.Format("Error Trace: {0}", Except.StackTrace));
|
||||
// while (Except.InnerException != null)
|
||||
// {
|
||||
// Except = Except.InnerException;
|
||||
// Logger.WriteDebug($"Inner exception: {Except.Message}");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//var pluginTasks = SharedLibraryCore.Plugins.PluginImporter.ActivePlugins.
|
||||
// Select(p => pluginHandlingAsync(p.OnEventAsync(E, this), p.Name));
|
||||
|
||||
//// execute all the plugin updates simultaneously
|
||||
//await Task.WhenAll(pluginTasks);
|
||||
|
||||
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||
{
|
||||
try
|
||||
@ -629,6 +594,13 @@ namespace IW4MAdmin
|
||||
// this are our new connecting clients
|
||||
foreach (var client in polledClients[0])
|
||||
{
|
||||
// this prevents duplicate events from being sent to the event api
|
||||
if (GetPlayersAsList().Count(c => c.NetworkId == client.NetworkId &&
|
||||
c.State == Player.ClientState.Connected) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Connect,
|
||||
@ -810,7 +782,7 @@ namespace IW4MAdmin
|
||||
logfile = await this.GetDvarAsync<string>("g_log");
|
||||
}
|
||||
|
||||
CustomCallback = await ScriptLoaded();
|
||||
//CustomCallback = await ScriptLoaded();
|
||||
string mainPath = EventParser.GetGameDir();
|
||||
#if DEBUG
|
||||
basepath.Value = @"D:\";
|
||||
|
@ -24,20 +24,20 @@ const plugin = {
|
||||
let usingVPN = false;
|
||||
|
||||
try {
|
||||
let httpRequest = System.Net.WebRequest.Create('https://api.xdefcon.com/proxy/check/?ip=' + origin.IPAddressString);
|
||||
let response = httpRequest.GetResponse();
|
||||
let data = response.GetResponseStream();
|
||||
let streamReader = new System.IO.StreamReader(data);
|
||||
let jsonResponse = streamReader.ReadToEnd();
|
||||
streamReader.Dispose();
|
||||
response.Close();
|
||||
let parsedJSON = JSON.parse(jsonResponse);
|
||||
let cl = new System.Net.Http.HttpClient();
|
||||
let re = cl.GetAsync('https://api.xdefcon.com/proxy/check/?ip=' + origin.IPAddressString).Result;
|
||||
let co = re.Content;
|
||||
let parsedJSON = JSON.parse(co.ReadAsStringAsync().Result);
|
||||
//co.Dispose();
|
||||
//re.Dispose();
|
||||
//cl.Dispose();
|
||||
usingVPN = parsedJSON['success'] && parsedJSON['proxy'];
|
||||
} catch (e) {
|
||||
this.logger.WriteError(e.message);
|
||||
}
|
||||
|
||||
if (usingVPN) {
|
||||
this.logger.WriteInfo(origin + ' is using a VPN (' + origin.IPAddressString + ')');
|
||||
let library = importNamespace('SharedLibraryCore');
|
||||
let kickOrigin = new library.Objects.Player();
|
||||
kickOrigin.ClientId = 1;
|
||||
|
@ -324,7 +324,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task AddScriptHit(bool isDamage, DateTime time, Player attacker, Player victim, int serverId, string map, string hitLoc, string type,
|
||||
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, string snapAngles)
|
||||
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, string fraction, string snapAngles)
|
||||
{
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
Vector3 vDeathOrigin = null;
|
||||
@ -362,7 +362,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
return;
|
||||
}
|
||||
|
||||
var kill = new EFClientKill()
|
||||
var hit = new EFClientKill()
|
||||
{
|
||||
Active = true,
|
||||
AttackerId = attacker.ClientId,
|
||||
@ -380,11 +380,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
When = time,
|
||||
IsKillstreakKill = isKillstreakKill[0] != '0',
|
||||
AdsPercent = float.Parse(Ads),
|
||||
Fraction = double.Parse(fraction),
|
||||
IsKill = !isDamage,
|
||||
AnglesList = snapshotAngles
|
||||
};
|
||||
|
||||
if (kill.DeathType == IW4Info.MeansOfDeath.MOD_SUICIDE &&
|
||||
kill.Damage == 100000)
|
||||
if (hit.DeathType == IW4Info.MeansOfDeath.MOD_SUICIDE &&
|
||||
hit.Damage == 100000)
|
||||
{
|
||||
// suicide by switching teams so let's not count it against them
|
||||
return;
|
||||
@ -395,7 +397,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
await AddStandardKill(attacker, victim);
|
||||
}
|
||||
|
||||
if (kill.IsKillstreakKill)
|
||||
if (hit.IsKillstreakKill)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -406,11 +408,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
clientStatsSvc.Update(clientStats);
|
||||
|
||||
// increment their hit count
|
||||
if (kill.DeathType == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET ||
|
||||
kill.DeathType == IW4Info.MeansOfDeath.MOD_RIFLE_BULLET ||
|
||||
kill.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
||||
if (hit.DeathType == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET ||
|
||||
hit.DeathType == IW4Info.MeansOfDeath.MOD_RIFLE_BULLET ||
|
||||
hit.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
||||
{
|
||||
clientStats.HitLocations.Single(hl => hl.Location == kill.HitLoc).HitCount += 1;
|
||||
clientStats.HitLocations.Single(hl => hl.Location == hit.HitLoc).HitCount += 1;
|
||||
}
|
||||
|
||||
if (Plugin.Config.Configuration().EnableAntiCheat)
|
||||
@ -478,11 +480,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
await executePenalty(clientDetection.ProcessKill(kill, isDamage));
|
||||
await executePenalty(clientDetection.ProcessKill(hit, isDamage));
|
||||
await executePenalty(clientDetection.ProcessTotalRatio(clientStats));
|
||||
|
||||
await clientStatsSvc.SaveChangesAsync();
|
||||
}
|
||||
|
||||
using (var ctx = new DatabaseContext())
|
||||
{
|
||||
ctx.Set<EFClientKill>().Add(hit);
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task AddStandardKill(Player attacker, Player victim)
|
||||
|
@ -29,6 +29,8 @@ namespace IW4MAdmin.Plugins.Stats.Models
|
||||
public Vector3 DeathOrigin { get; set; }
|
||||
public Vector3 ViewAngles { get; set; }
|
||||
public DateTime When { get; set; }
|
||||
public double Fraction { get; set; }
|
||||
public bool IsKill { get; set; }
|
||||
// http://wiki.modsrepository.com/index.php?title=Call_of_Duty_5:_Gameplay_standards for conversion to meters
|
||||
[NotMapped]
|
||||
public double Distance => Vector3.Distance(KillOrigin, DeathOrigin) * 0.0254;
|
||||
|
@ -73,10 +73,10 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
break;
|
||||
case GameEvent.EventType.ScriptKill:
|
||||
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||
if (killInfo.Length >= 13)
|
||||
if (killInfo.Length >= 14)
|
||||
{
|
||||
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, S.GetHashCode(), 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[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14]);
|
||||
}
|
||||
break;
|
||||
case GameEvent.EventType.Kill:
|
||||
@ -84,15 +84,15 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
await Manager.AddStandardKill(E.Origin, E.Target);
|
||||
break;
|
||||
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());
|
||||
break;
|
||||
case GameEvent.EventType.ScriptDamage:
|
||||
killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||
if (killInfo.Length >= 13)
|
||||
if (killInfo.Length >= 14)
|
||||
{
|
||||
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, S.GetHashCode(), 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[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace IW4MAdmin.Plugins.Stats.Web.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
// [Authorize]
|
||||
public async Task<IActionResult> GetAutomatedPenaltyInfoAsync(int clientId)
|
||||
{
|
||||
using (var ctx = new SharedLibraryCore.Database.DatabaseContext())
|
||||
|
29
Plugins/Tests/ClientTests.cs
Normal file
29
Plugins/Tests/ClientTests.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
public class ClientTests
|
||||
{
|
||||
[Fact]
|
||||
public void SetAdditionalPropertyShouldSucceed()
|
||||
{
|
||||
var client = new Player();
|
||||
int newProp = 5;
|
||||
client.SetAdditionalProperty("NewProp", newProp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdditionalPropertyShouldSucceed()
|
||||
{
|
||||
var client = new Player();
|
||||
int newProp = 5;
|
||||
client.SetAdditionalProperty("NewProp", newProp);
|
||||
|
||||
Assert.True(client.GetAdditionalProperty<int>("NewProp") == 5, "added property does not match retrieved property");
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,6 @@ namespace SharedLibraryCore.Database
|
||||
currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
|
||||
$"{Path.DirectorySeparatorChar}{currentPath}" :
|
||||
currentPath;
|
||||
// todo: fix later
|
||||
|
||||
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = $"{currentPath}{Path.DirectorySeparatorChar}Database.db".Substring(6) };
|
||||
var connectionString = connectionStringBuilder.ToString();
|
||||
@ -100,10 +99,6 @@ namespace SharedLibraryCore.Database
|
||||
|
||||
// adapted from
|
||||
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
|
||||
//#if DEBUG == TRUE
|
||||
// // foreach (string dllPath in Directory.GetFiles($"{Utilities.OperatingDirectory}Plugins"))
|
||||
//#else
|
||||
//todo: fix the debug thingie for entity scanning
|
||||
IEnumerable<string> directoryFiles;
|
||||
|
||||
string pluginDir = $@"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}Debug{Path.DirectorySeparatorChar}netcoreapp2.0{Path.DirectorySeparatorChar}Plugins";
|
||||
@ -119,9 +114,11 @@ namespace SharedLibraryCore.Database
|
||||
}
|
||||
|
||||
directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.Contains(".dll"));
|
||||
|
||||
#if DEBUG == TRUE
|
||||
foreach (string dllPath in Directory.GetFiles(@"C:\Projects\IW4M-Admin\Application\bin\Debug\netcoreapp2.1\Plugins"))
|
||||
#else
|
||||
foreach (string dllPath in directoryFiles)
|
||||
//#endif
|
||||
#endif
|
||||
{
|
||||
Assembly library;
|
||||
try
|
||||
|
@ -16,6 +16,7 @@ namespace SharedLibraryCore.Dtos
|
||||
public long NetworkId { get; set; }
|
||||
public List<string> Aliases { get; set; }
|
||||
public List<string> IPs { get; set; }
|
||||
public bool HasActivePenalty { get; set; }
|
||||
public int ConnectionCount { get; set; }
|
||||
public string LastSeen { get; set; }
|
||||
public string FirstSeen { get; set; }
|
||||
|
665
SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.Designer.cs
generated
Normal file
665
SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.Designer.cs
generated
Normal file
@ -0,0 +1,665 @@
|
||||
// <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("20180902035612_AddFractionAndIsKill")]
|
||||
partial class AddFractionAndIsKill
|
||||
{
|
||||
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<int>("SnapshotId")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
b.Property<int>("ClientId");
|
||||
|
||||
b.Property<int>("CurrentSessionLength");
|
||||
|
||||
b.Property<double>("CurrentStrain");
|
||||
|
||||
b.Property<int?>("CurrentViewAngleVector3Id");
|
||||
|
||||
b.Property<int>("Deaths");
|
||||
|
||||
b.Property<double>("Distance");
|
||||
|
||||
b.Property<double>("EloRating");
|
||||
|
||||
b.Property<int?>("HitDestinationVector3Id");
|
||||
|
||||
b.Property<int>("HitLocation");
|
||||
|
||||
b.Property<int?>("HitOriginVector3Id");
|
||||
|
||||
b.Property<int>("HitType");
|
||||
|
||||
b.Property<int>("Hits");
|
||||
|
||||
b.Property<int>("Kills");
|
||||
|
||||
b.Property<int?>("LastStrainAngleVector3Id");
|
||||
|
||||
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("CurrentViewAngleVector3Id");
|
||||
|
||||
b.HasIndex("HitDestinationVector3Id");
|
||||
|
||||
b.HasIndex("HitOriginVector3Id");
|
||||
|
||||
b.HasIndex("LastStrainAngleVector3Id");
|
||||
|
||||
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<int>("ServerId");
|
||||
|
||||
b.Property<int>("VictimId");
|
||||
|
||||
b.Property<int?>("ViewAnglesVector3Id");
|
||||
|
||||
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<int>("ServerId");
|
||||
|
||||
b.Property<DateTime>("TimeSent");
|
||||
|
||||
b.HasKey("MessageId");
|
||||
|
||||
b.HasIndex("ClientId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
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<int>("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.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<int>("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<int?>("ServerId");
|
||||
|
||||
b.HasKey("RatingId");
|
||||
|
||||
b.HasIndex("RatingHistoryId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.ToTable("EFRating");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
|
||||
{
|
||||
b.Property<int>("ServerId");
|
||||
|
||||
b.Property<bool>("Active");
|
||||
|
||||
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<int>("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();
|
||||
|
||||
b.HasKey("AliasId");
|
||||
|
||||
b.HasIndex("IPAddress");
|
||||
|
||||
b.HasIndex("LinkId");
|
||||
|
||||
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<int>("OriginEntityId");
|
||||
|
||||
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("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
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace SharedLibraryCore.Migrations
|
||||
{
|
||||
public partial class AddFractionAndIsKill : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "Fraction",
|
||||
table: "EFClientKills",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsKill",
|
||||
table: "EFClientKills",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EFChangeHistory",
|
||||
columns: table => new
|
||||
{
|
||||
Active = table.Column<bool>(nullable: false),
|
||||
ChangeHistoryId = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
OriginEntityId = table.Column<int>(nullable: false),
|
||||
TargetEntityId = table.Column<int>(nullable: false),
|
||||
TypeOfChange = table.Column<int>(nullable: false),
|
||||
TimeChanged = table.Column<DateTime>(nullable: false),
|
||||
Comment = table.Column<string>(maxLength: 128, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EFChangeHistory", x => x.ChangeHistoryId);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "EFChangeHistory");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Vector3_EFACSnapshotSnapshotId",
|
||||
table: "Vector3");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Fraction",
|
||||
table: "EFClientKills");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsKill",
|
||||
table: "EFClientKills");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,9 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using SharedLibraryCore.Database;
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Migrations
|
||||
{
|
||||
@ -18,7 +14,7 @@ namespace SharedLibraryCore.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
||||
.HasAnnotation("ProductVersion", "2.1.2-rtm-30932");
|
||||
|
||||
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||
{
|
||||
@ -99,8 +95,12 @@ namespace SharedLibraryCore.Migrations
|
||||
|
||||
b.Property<int>("DeathType");
|
||||
|
||||
b.Property<double>("Fraction");
|
||||
|
||||
b.Property<int>("HitLoc");
|
||||
|
||||
b.Property<bool>("IsKill");
|
||||
|
||||
b.Property<int?>("KillOriginVector3Id");
|
||||
|
||||
b.Property<int>("Map");
|
||||
@ -331,6 +331,29 @@ namespace SharedLibraryCore.Migrations
|
||||
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<int>("OriginEntityId");
|
||||
|
||||
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")
|
||||
|
@ -34,15 +34,45 @@ namespace SharedLibraryCore.Objects
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
/// <summary>
|
||||
/// client has been banned
|
||||
/// </summary>
|
||||
Banned = -1,
|
||||
/// <summary>
|
||||
/// default client state upon first connect
|
||||
/// </summary>
|
||||
User = 0,
|
||||
/// <summary>
|
||||
/// client has been flagged
|
||||
/// </summary>
|
||||
Flagged = 1,
|
||||
/// <summary>
|
||||
/// client is trusted
|
||||
/// </summary>
|
||||
Trusted = 2,
|
||||
/// <summary>
|
||||
/// client is a moderator
|
||||
/// </summary>
|
||||
Moderator = 3,
|
||||
/// <summary>
|
||||
/// client is an administrator
|
||||
/// </summary>
|
||||
Administrator = 4,
|
||||
/// <summary>
|
||||
/// client is a senior administrator
|
||||
/// </summary>
|
||||
SeniorAdmin = 5,
|
||||
/// <summary>
|
||||
/// client is a owner
|
||||
/// </summary>
|
||||
Owner = 6,
|
||||
/// <summary>
|
||||
/// not used
|
||||
/// </summary>
|
||||
Creator = 7,
|
||||
/// <summary>
|
||||
/// reserved for default account
|
||||
/// </summary>
|
||||
Console = 8
|
||||
}
|
||||
|
||||
@ -51,12 +81,10 @@ namespace SharedLibraryCore.Objects
|
||||
ConnectionTime = DateTime.UtcNow;
|
||||
ClientNumber = -1;
|
||||
DelayedEvents = new Queue<GameEvent>();
|
||||
_additionalProperties = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Name}::{NetworkId}";
|
||||
}
|
||||
public override string ToString() => $"{Name}::{NetworkId}";
|
||||
|
||||
public String GetLastConnection()
|
||||
{
|
||||
@ -105,7 +133,10 @@ namespace SharedLibraryCore.Objects
|
||||
{
|
||||
await CurrentServer.Ban(Message, this, Sender);
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
Dictionary<string, object> _additionalProperties;
|
||||
public T GetAdditionalProperty<T>(string name) => (T)_additionalProperties[name];
|
||||
public void SetAdditionalProperty(string name, object value) => _additionalProperties.Add(name, value);
|
||||
[NotMapped]
|
||||
public int ClientNumber { get; set; }
|
||||
[NotMapped]
|
||||
@ -150,9 +181,6 @@ namespace SharedLibraryCore.Objects
|
||||
return ((Player)obj).NetworkId == NetworkId;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return NetworkId.GetHashCode();
|
||||
}
|
||||
public override int GetHashCode() => (int)NetworkId;
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ namespace SharedLibraryCore
|
||||
ScriptEngine = new Jint.Engine(cfg =>
|
||||
cfg.AllowClr(new[]
|
||||
{
|
||||
typeof(System.Net.WebRequest).Assembly,
|
||||
typeof(System.Net.Http.HttpClient).Assembly,
|
||||
typeof(Objects.Player).Assembly,
|
||||
})
|
||||
.CatchClrExceptions());
|
||||
|
@ -179,13 +179,9 @@ namespace SharedLibraryCore
|
||||
/// <param name="message">Message to send out</param>
|
||||
public async Task ToAdmins(String message)
|
||||
{
|
||||
foreach (Player P in Players)
|
||||
foreach (var client in GetPlayersAsList().Where(c => c.Level > Player.Permission.Flagged))
|
||||
{
|
||||
if (P == null)
|
||||
continue;
|
||||
|
||||
if (P.Level > Player.Permission.Flagged)
|
||||
await P.Tell(message);
|
||||
await client.Tell(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,6 +235,8 @@ namespace SharedLibraryCore.Services
|
||||
|
||||
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int aliasId, int ip = 0)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
using (var context = new DatabaseContext())
|
||||
{
|
||||
var iqPenalties = await (from link in context.AliasLinks
|
||||
@ -242,6 +244,8 @@ namespace SharedLibraryCore.Services
|
||||
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)
|
||||
{
|
||||
@ -250,6 +254,8 @@ namespace SharedLibraryCore.Services
|
||||
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;
|
||||
|
@ -20,6 +20,7 @@
|
||||
<PackageReference Include="Jint" Version="3.0.0-beta-1249" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="2.1.1" />
|
||||
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using WebfrontCore.ViewModels;
|
||||
using static SharedLibraryCore.Objects.Player;
|
||||
|
||||
namespace WebfrontCore.Controllers
|
||||
{
|
||||
@ -22,6 +23,20 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
Name = "Reason",
|
||||
Label = Localization["WEBFRONT_ACTION_LABEL_REASON"],
|
||||
},
|
||||
new InputInfo()
|
||||
{
|
||||
Name ="Duration",
|
||||
Label=Localization["WEBFRONT_ACTION_LABEL_DURATION"],
|
||||
Type="select",
|
||||
Values = new Dictionary<string, string>()
|
||||
{
|
||||
{"1", $"1 {Localization["GLOBAL_TIME_HOUR"]}" },
|
||||
{"2", $"6 {Localization["GLOBAL_TIME_HOURS"]}" },
|
||||
{"3", $"1 {Localization["GLOBAL_TIME_DAY"]}" },
|
||||
{"4", $"1 {Localization["GLOBAL_TIME_WEEK"]}" },
|
||||
{"5", $"{Localization["WEBFRONT_ACTION_SELECTION_PERMANENT"]}" },
|
||||
}
|
||||
}
|
||||
},
|
||||
Action = "BanAsync"
|
||||
@ -30,14 +45,36 @@ namespace WebfrontCore.Controllers
|
||||
return View("_ActionForm", info);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> BanAsync(int targetId, string Reason)
|
||||
public async Task<IActionResult> BanAsync(int targetId, string Reason, int Duration)
|
||||
{
|
||||
string duration = string.Empty;
|
||||
|
||||
switch (Duration)
|
||||
{
|
||||
case 1:
|
||||
duration = "1h";
|
||||
break;
|
||||
case 2:
|
||||
duration = "6h";
|
||||
break;
|
||||
case 3:
|
||||
duration = "1d";
|
||||
break;
|
||||
case 4:
|
||||
duration = "1w";
|
||||
break;
|
||||
}
|
||||
|
||||
string command = Duration == 5 ?
|
||||
$"!ban @{targetId} {Reason}" :
|
||||
$"!tempban @{targetId} {duration} {Reason}";
|
||||
|
||||
var server = Manager.GetServers().First();
|
||||
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.GetHashCode(),
|
||||
command = $"!ban @{targetId} {Reason}"
|
||||
command
|
||||
}));
|
||||
}
|
||||
|
||||
@ -102,5 +139,42 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
return await Task.FromResult(RedirectToAction("LoginAsync", "Account", new { clientId, password }));
|
||||
}
|
||||
|
||||
public IActionResult EditForm()
|
||||
{
|
||||
var info = new ActionInfo()
|
||||
{
|
||||
ActionButtonLabel = Localization["WEBFRONT_ACTION_LABEL_EDIT"],
|
||||
Name = "Edit",
|
||||
Inputs = new List<InputInfo>()
|
||||
{
|
||||
new InputInfo()
|
||||
{
|
||||
Name ="level",
|
||||
Label=Localization["WEBFRONT_PROFILE_LEVEL"],
|
||||
Type="select",
|
||||
Values = Enum.GetValues(typeof(Permission)).OfType<Permission>()
|
||||
.Where(p => p <= Client.Level)
|
||||
.Where(p => p != Permission.Banned)
|
||||
.Where(p => p != Permission.Flagged)
|
||||
.ToDictionary(p => p.ToString(), p=> p.ToLocalizedLevelName())
|
||||
},
|
||||
},
|
||||
Action = "EditAsync"
|
||||
};
|
||||
|
||||
return View("_ActionForm", info);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> EditAsync(int targetId, string level)
|
||||
{
|
||||
var server = Manager.GetServers().First();
|
||||
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.GetHashCode(),
|
||||
command = $"!setlevel @{targetId} {level}"
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static SharedLibraryCore.Objects.Penalty;
|
||||
|
||||
namespace WebfrontCore.Controllers
|
||||
{
|
||||
@ -20,6 +21,8 @@ namespace WebfrontCore.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var activePenalties = await Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId, client.IPAddress);
|
||||
|
||||
#if DEBUG
|
||||
Authorized = true;
|
||||
#endif
|
||||
@ -48,6 +51,7 @@ namespace WebfrontCore.Controllers
|
||||
.Distinct()
|
||||
.OrderBy(i => i)
|
||||
.ToList(),
|
||||
HasActivePenalty = activePenalties.Count > 0,
|
||||
Online = Manager.GetActiveClients().FirstOrDefault(c => c.ClientId == client.ClientId) != null,
|
||||
TimeOnline = (DateTime.UtcNow - client.LastConnection).TimeSpanText(),
|
||||
LinkedAccounts = client.LinkedAccounts
|
||||
|
@ -12,5 +12,7 @@ namespace WebfrontCore.ViewModels
|
||||
public string Placeholder { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Value { get; set; }
|
||||
public Dictionary<string, string> Values { get; set; }
|
||||
public bool Checked { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,30 @@
|
||||
string inputType = input.Type ?? "text";
|
||||
string value = input.Value ?? "";
|
||||
|
||||
if (inputType == "select")
|
||||
{
|
||||
<select name="@input.Name" class="form-control" aria-label="@input.Name" aria-describedby="basic-addon-@input.Name">
|
||||
@foreach (var item in input.Values)
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
|
||||
else if (inputType == "checkbox")
|
||||
{
|
||||
<div class="btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-primary active">
|
||||
<input type="checkbox" name="@input.Name" @(input.Checked ? "checked" : "") autocomplete="off">@input.Label
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
<input type="@inputType" name="@input.Name" value="@value" class="form-control" placeholder="@input.Placeholder" aria-label="@input.Name" aria-describedby="basic-addon-@input.Name">
|
||||
}
|
||||
}
|
||||
|
||||
</div>
|
||||
}
|
||||
|
@ -33,18 +33,20 @@
|
||||
{
|
||||
<div class="d-flex d-md-inline-flex justify-content-center order-1">
|
||||
<div id="profile_aliases_btn" class="oi oi-caret-bottom h3 ml-0 ml-md-2"></div>
|
||||
|
||||
@if (Model.LevelInt < (int)ViewBag.User.Level &&
|
||||
(SharedLibraryCore.Objects.Player.Permission)Model.LevelInt != SharedLibraryCore.Objects.Player.Permission.Banned)
|
||||
@if (Model.LevelInt != -1)
|
||||
{
|
||||
<div id="profile_action_edit_btn" class="profile-action oi oi-cog text-muted h3 ml-2" title="Client Options" data-action="edit" aria-hidden="true"></div>
|
||||
}
|
||||
@if (Model.LevelInt < (int)ViewBag.User.Level && !Model.HasActivePenalty)
|
||||
{
|
||||
<div id="profile_action_ban_btn" class="profile-action oi oi-lock-unlocked text-success h3 ml-2" title="Ban Client" data-action="ban" aria-hidden="true"></div>
|
||||
}
|
||||
|
||||
@if (Model.LevelInt < (int)ViewBag.User.Level &&
|
||||
(SharedLibraryCore.Objects.Player.Permission)Model.LevelInt == SharedLibraryCore.Objects.Player.Permission.Banned)
|
||||
@if (Model.LevelInt < (int)ViewBag.User.Level && Model.HasActivePenalty)
|
||||
{
|
||||
<div id="profile_action_unban_btn" class="profile-action oi oi-lock-locked text-danger h3 ml-2" title="Unban Client" data-action="unban" aria-hidden="true"></div>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<div id="profile_aliases" class="pr-0 pr-sm-4 pb-2 mb-2 text-muted order-0">
|
||||
|
@ -6,6 +6,7 @@
|
||||
@{
|
||||
foreach (var response in Model)
|
||||
{
|
||||
<span class="text-success">@response.Response</span><br />
|
||||
<span class="text-muted">@response.Response</span><br />
|
||||
}
|
||||
<hr />
|
||||
}
|
@ -6321,6 +6321,9 @@ a.link-inverse:hover {
|
||||
#console_command_response {
|
||||
min-height: 20rem; }
|
||||
|
||||
#console_command_response hr {
|
||||
border-color: #6c757d; }
|
||||
|
||||
#console .form-control, #console button {
|
||||
border-radius: 0;
|
||||
border-color: #007ACC;
|
||||
@ -6339,7 +6342,7 @@ a.link-inverse:hover {
|
||||
form *, select {
|
||||
border-radius: 0 !important; }
|
||||
|
||||
select {
|
||||
#penalty_filter_selection {
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
border-bottom: none !important;
|
||||
|
@ -96,6 +96,10 @@ a.link-inverse:hover {
|
||||
min-height: 20rem;
|
||||
}
|
||||
|
||||
#console_command_response hr {
|
||||
border-color: #6c757d;
|
||||
}
|
||||
|
||||
#console .form-control, #console button {
|
||||
border-radius: 0;
|
||||
border-color: $primary;
|
||||
@ -119,7 +123,7 @@ form *, select {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
select {
|
||||
#penalty_filter_selection {
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
border-bottom: none !important;
|
||||
@ -205,4 +209,3 @@ select {
|
||||
.client-message, .automated-penalty-info-detailed {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ $(document).ready(function () {
|
||||
* hide loader when clicking
|
||||
*/
|
||||
$(document).click(function (e) {
|
||||
hideLoader()
|
||||
//hideLoader()
|
||||
});
|
||||
|
||||
/*
|
||||
@ -39,7 +39,7 @@ $(document).ready(function () {
|
||||
$('#actionModal').modal();
|
||||
})
|
||||
.fail(function (jqxhr, textStatus, error) {
|
||||
$('#actionModal .modal-message').text('Error &mdash ' + error);
|
||||
$('#actionModal .modal-message').text('Error — ' + error);
|
||||
$('#actionModal').modal();
|
||||
$('#actionModal .modal-message').fadeIn('fast');
|
||||
});
|
||||
|
@ -14,7 +14,7 @@
|
||||
$.get('/Console/ExecuteAsync', { serverId: serverId, command: command })
|
||||
.done(function (response) {
|
||||
hideLoader();
|
||||
$('#console_command_response').html(response);
|
||||
$('#console_command_response').append(response);
|
||||
$('#console_command_value').val("");
|
||||
})
|
||||
.fail(function (jqxhr, textStatus, error) {
|
||||
|
@ -14,6 +14,7 @@ init()
|
||||
level.callbackPlayerDamage = ::Callback_PlayerDamage;
|
||||
}
|
||||
|
||||
|
||||
onPlayerConnect(player)
|
||||
{
|
||||
for(;;)
|
||||
@ -111,6 +112,11 @@ waitForAdditionalAngles(logString)
|
||||
logPrint(logString + ";" + anglesStr + "\n");
|
||||
}
|
||||
|
||||
vectorScale(vector, scale)
|
||||
{
|
||||
return (vector[0] * scale, vector[1] * scale, vector[2] * scale);
|
||||
}
|
||||
|
||||
Process_Hit(type, attacker, sHitLoc, sMeansOfDeath, iDamage, sWeapon)
|
||||
{
|
||||
victim = self;
|
||||
@ -123,7 +129,12 @@ Process_Hit(type, attacker, sHitLoc, sMeansOfDeath, iDamage, sWeapon)
|
||||
location = victim GetTagOrigin(hitLocationToBone(sHitLoc));
|
||||
isKillstreakKill = !isPlayer(attacker) || isKillstreakWeapon(sWeapon);
|
||||
|
||||
logLine = "Script" + type + ";" + _attacker.guid + ";" + victim.guid + ";" + _attacker GetTagOrigin("tag_eye") + ";" + location + ";" + iDamage + ";" + sWeapon + ";" + sHitLoc + ";" + sMeansOfDeath + ";" + _attacker getPlayerAngles() + ";" + gettime() + ";" + isKillstreakKill + ";" + _attacker playerADS();
|
||||
// do the tracing stuff
|
||||
start = _attacker getTagOrigin("tag_eye");
|
||||
end = location;
|
||||
trace = bulletTrace(start, end, true, _attacker);
|
||||
|
||||
logLine = "Script" + type + ";" + _attacker.guid + ";" + victim.guid + ";" + _attacker GetTagOrigin("tag_eye") + ";" + location + ";" + iDamage + ";" + sWeapon + ";" + sHitLoc + ";" + sMeansOfDeath + ";" + _attacker getPlayerAngles() + ";" + gettime() + ";" + isKillstreakKill + ";" + _attacker playerADS() + ";" + trace["fraction"];
|
||||
attacker thread waitForAdditionalAngles(logLine);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user