Compare commits

..

7 Commits

Author SHA1 Message Date
e56f574af4 fix introduced bug :) 2020-10-01 19:06:12 -05:00
513f495304 anticheat tweaks
- reset recoil state on map change
- refactor config
- remove m21 from chest detection
- allow ignored client ids
2020-10-01 19:05:52 -05:00
910faf427b enhance script plugin features
(support service resolver with generic args)
(support requiresTarget for command)
2020-10-01 19:05:38 -05:00
9117440566 merge to pre (#172)
* update GenerateGuidFromString to resolve to a stable hash code.
fix bots not showing up on live radar

* add 0.0.0.0 as internal "ip" even though it's not actually a valid IP but for cod4x

* implement pm admins command for issue #170

* implement service resolver for script plugins
2020-09-26 18:15:56 -05:00
ad6b6a6465 merge to pre (#169)
* update GenerateGuidFromString to resolve to a stable hash code.
fix bots not showing up on live radar

* add 0.0.0.0 as internal "ip" even though it's not actually a valid IP but for cod4x
2020-09-21 15:37:31 -05:00
eb8145a168 add 0.0.0.0 as internal "ip" even though it's not actually a valid IP but for cod4x 2020-09-04 12:58:54 -05:00
a560e05df8 update pipeline file for seperate builds 2020-08-31 12:33:39 -05:00
686 changed files with 6839 additions and 129623 deletions

4
.gitignore vendored
View File

@ -244,7 +244,3 @@ launchSettings.json
/Tests/ApplicationTests/Files/GameEvents.json
/Tests/ApplicationTests/Files/replay.json
/GameLogServer/game_log_server_env
.idea/*
*.db
/Data/IW4MAdmin_Migration.db-shm
/Data/IW4MAdmin_Migration.db-wal

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
using IW4MAdmin.Application.Misc;
using Newtonsoft.Json;
using RestEase;
using SharedLibraryCore.Helpers;
@ -37,13 +35,6 @@ namespace IW4MAdmin.Application.API.Master
public string Message { get; set; }
}
public class PluginSubscriptionContent
{
public string Content { get; set; }
public PluginType Type { get; set; }
}
/// <summary>
/// Defines the capabilities of the master API
/// </summary>
@ -72,8 +63,5 @@ namespace IW4MAdmin.Application.API.Master
[Get("localization/{languageTag}")]
Task<SharedLibraryCore.Localization.Layout> GetLocalization([Path("languageTag")] string languageTag);
[Get("plugin_subscriptions")]
Task<IEnumerable<PluginSubscriptionContent>> GetPluginSubscription([Query("instance_id")] Guid instanceId, [Query("subscription_id")] string subscription_id);
}
}

View File

@ -5,7 +5,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
<Version>2020.0.0.0</Version>
<Version>2.3.2.0</Version>
<Authors>RaidMax</Authors>
<Company>Forever None</Company>
<Product>IW4MAdmin</Product>
@ -25,13 +25,13 @@
<ItemGroup>
<PackageReference Include="Jint" Version="3.0.0-beta-1632" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.10">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.10" />
<PackageReference Include="RestEase" Version="1.5.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.7" />
<PackageReference Include="RestEase" Version="1.5.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
</ItemGroup>
<PropertyGroup>
@ -39,6 +39,7 @@
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<TieredCompilation>true</TieredCompilation>
<LangVersion>Latest</LangVersion>
<StartupObject></StartupObject>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Prerelease|AnyCPU'">
@ -48,8 +49,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Integrations\Cod\Integrations.Cod.csproj" />
<ProjectReference Include="..\Integrations\Source\Integrations.Source.csproj" />
<ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj">
<Private>true</Private>
</ProjectReference>
@ -60,9 +59,6 @@
<None Update="DefaultSettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configuration\LoggingConfiguration.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">

View File

@ -1,15 +1,19 @@
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.API.Master;
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.Extensions;
using IW4MAdmin.Application.Misc;
using IW4MAdmin.Application.RConParsers;
using IW4MAdmin.Application.RconParsers;
using SharedLibraryCore;
using SharedLibraryCore.Commands;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Configuration.Validation;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using SharedLibraryCore.Services;
using System;
using System.Collections;
@ -20,15 +24,7 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Context;
using IW4MAdmin.Application.Migration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using static SharedLibraryCore.GameEvent;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using ObsoleteLogger = SharedLibraryCore.Interfaces.ILogger;
namespace IW4MAdmin.Application
{
@ -36,7 +32,7 @@ namespace IW4MAdmin.Application
{
private readonly ConcurrentBag<Server> _servers;
public List<Server> Servers => _servers.OrderByDescending(s => s.ClientNum).ToList();
[Obsolete] public ObsoleteLogger Logger => _serviceProvider.GetRequiredService<ObsoleteLogger>();
public ILogger Logger => GetLogger(0);
public bool IsRunning { get; private set; }
public bool IsInitialized { get; private set; }
public DateTime StartTime { get; private set; }
@ -54,9 +50,11 @@ namespace IW4MAdmin.Application
private readonly ILogger _logger;
private readonly List<MessageToken> MessageTokens;
private readonly ClientService ClientSvc;
readonly AliasService AliasSvc;
readonly PenaltyService PenaltySvc;
public IConfigurationHandler<ApplicationConfiguration> ConfigHandler;
readonly IPageList PageList;
private readonly Dictionary<long, ILogger> _loggers = new Dictionary<long, ILogger>();
private readonly IMetaService _metaService;
private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0);
private readonly CancellationTokenSource _tokenSource;
@ -70,33 +68,30 @@ namespace IW4MAdmin.Application
private readonly IScriptCommandFactory _scriptCommandFactory;
private readonly IMetaRegistration _metaRegistration;
private readonly IScriptPluginServiceResolver _scriptPluginServiceResolver;
private readonly IServiceProvider _serviceProvider;
private readonly ChangeHistoryService _changeHistoryService;
private readonly ApplicationConfiguration _appConfig;
public ConcurrentDictionary<long, GameEvent> ProcessingEvents { get; } = new ConcurrentDictionary<long, GameEvent>();
public ApplicationManager(ILogger<ApplicationManager> logger, IMiddlewareActionHandler actionHandler, IEnumerable<IManagerCommand> commands,
public ApplicationManager(ILogger logger, IMiddlewareActionHandler actionHandler, IEnumerable<IManagerCommand> commands,
ITranslationLookup translationLookup, IConfigurationHandler<CommandConfiguration> commandConfiguration,
IConfigurationHandler<ApplicationConfiguration> appConfigHandler, IGameServerInstanceFactory serverInstanceFactory,
IEnumerable<IPlugin> plugins, IParserRegexFactory parserRegexFactory, IEnumerable<IRegisterEvent> customParserEvents,
IEventHandler eventHandler, IScriptCommandFactory scriptCommandFactory, IDatabaseContextFactory contextFactory, IMetaService metaService,
IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver, ClientService clientService, IServiceProvider serviceProvider,
ChangeHistoryService changeHistoryService, ApplicationConfiguration appConfig, PenaltyService penaltyService)
IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver)
{
MiddlewareActionHandler = actionHandler;
_servers = new ConcurrentBag<Server>();
MessageTokens = new List<MessageToken>();
ClientSvc = clientService;
PenaltySvc = penaltyService;
ClientSvc = new ClientService(contextFactory);
AliasSvc = new AliasService();
PenaltySvc = new PenaltyService();
ConfigHandler = appConfigHandler;
StartTime = DateTime.UtcNow;
PageList = new PageList();
AdditionalEventParsers = new List<IEventParser>() { new BaseEventParser(parserRegexFactory, logger, _appConfig) };
AdditionalRConParsers = new List<IRConParser>() { new BaseRConParser(serviceProvider.GetRequiredService<ILogger<BaseRConParser>>(), parserRegexFactory) };
AdditionalEventParsers = new List<IEventParser>() { new BaseEventParser(parserRegexFactory, logger, appConfigHandler.Configuration()) };
AdditionalRConParsers = new List<IRConParser>() { new BaseRConParser(parserRegexFactory) };
TokenAuthenticator = new TokenAuthentication();
_logger = logger;
_metaService = metaService;
_tokenSource = new CancellationTokenSource();
_loggers.Add(0, logger);
_commands = commands.ToList();
_translationLookup = translationLookup;
_commandConfiguration = commandConfiguration;
@ -107,9 +102,6 @@ namespace IW4MAdmin.Application
_scriptCommandFactory = scriptCommandFactory;
_metaRegistration = metaRegistration;
_scriptPluginServiceResolver = scriptPluginServiceResolver;
_serviceProvider = serviceProvider;
_changeHistoryService = changeHistoryService;
_appConfig = appConfig;
Plugins = plugins;
}
@ -117,7 +109,9 @@ namespace IW4MAdmin.Application
public async Task ExecuteEvent(GameEvent newEvent)
{
ProcessingEvents.TryAdd(newEvent.Id, newEvent);
#if DEBUG == true
Logger.WriteDebug($"Entering event process for {newEvent.Id}");
#endif
// the event has failed already
if (newEvent.Failed)
@ -130,17 +124,22 @@ namespace IW4MAdmin.Application
await newEvent.Owner.ExecuteEvent(newEvent);
// save the event info to the database
await _changeHistoryService.Add(newEvent);
var changeHistorySvc = new ChangeHistoryService();
await changeHistorySvc.Add(newEvent);
#if DEBUG
Logger.WriteDebug($"Processed event with id {newEvent.Id}");
#endif
}
catch (TaskCanceledException)
{
_logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id);
Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early");
}
catch (OperationCanceledException)
{
_logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id);
Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early");
}
// this happens if a plugin requires login
@ -153,58 +152,31 @@ namespace IW4MAdmin.Application
catch (NetworkException ex)
{
newEvent.FailReason = EventFailReason.Exception;
using (LogContext.PushProperty("Server", newEvent.Owner?.ToString()))
{
_logger.LogError(ex, ex.Message);
}
Logger.WriteError(ex.Message);
Logger.WriteDebug(ex.GetExceptionInfo());
}
catch (ServerException ex)
{
newEvent.FailReason = EventFailReason.Exception;
using (LogContext.PushProperty("Server", newEvent.Owner?.ToString()))
{
_logger.LogError(ex, ex.Message);
}
Logger.WriteWarning(ex.Message);
}
catch (Exception ex)
{
newEvent.FailReason = EventFailReason.Exception;
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner));
using (LogContext.PushProperty("Server", newEvent.Owner?.ToString()))
{
_logger.LogError(ex, "Unexpected exception");
}
}
skip:
if (newEvent.Type == EventType.Command && newEvent.ImpersonationOrigin == null)
{
var correlatedEvents =
ProcessingEvents.Values.Where(ev =>
ev.CorrelationId == newEvent.CorrelationId && ev.Id != newEvent.Id)
.ToList();
await Task.WhenAll(correlatedEvents.Select(ev =>
ev.WaitAsync(Utilities.DefaultCommandTimeout, CancellationToken)));
newEvent.Output.AddRange(correlatedEvents.SelectMany(ev => ev.Output));
foreach (var correlatedEvent in correlatedEvents)
{
ProcessingEvents.Remove(correlatedEvent.Id, out _);
}
}
// we don't want to remove events that are correlated to command
if (ProcessingEvents.Values.ToList()?.Count(gameEvent => gameEvent.CorrelationId == newEvent.CorrelationId) == 1)
{
ProcessingEvents.Remove(newEvent.Id, out _);
Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner));
Logger.WriteDebug(ex.GetExceptionInfo());
}
skip:
// tell anyone waiting for the output that we're done
newEvent.Complete();
OnGameEventExecuted?.Invoke(this, newEvent);
#if DEBUG == true
Logger.WriteDebug($"Exiting event process for {newEvent.Id}");
#endif
}
public IList<Server> GetServers()
@ -220,15 +192,15 @@ namespace IW4MAdmin.Application
public async Task UpdateServerStates()
{
// store the server hash code and task for it
var runningUpdateTasks = new Dictionary<long, (Task task, CancellationTokenSource tokenSource, DateTime startTime)>();
var runningUpdateTasks = new Dictionary<long, Task>();
while (!_tokenSource.IsCancellationRequested)
{
// select the server ids that have completed the update task
var serverTasksToRemove = runningUpdateTasks
.Where(ut => ut.Value.task.Status == TaskStatus.RanToCompletion ||
ut.Value.task.Status == TaskStatus.Canceled || // we want to cancel if a task takes longer than 5 minutes
ut.Value.task.Status == TaskStatus.Faulted || DateTime.Now - ut.Value.startTime > TimeSpan.FromMinutes(5))
.Where(ut => ut.Value.Status == TaskStatus.RanToCompletion ||
ut.Value.Status == TaskStatus.Canceled ||
ut.Value.Status == TaskStatus.Faulted)
.Select(ut => ut.Key)
.ToList();
@ -239,14 +211,9 @@ namespace IW4MAdmin.Application
IsInitialized = true;
}
// remove the update tasks as they have completed
foreach (var serverId in serverTasksToRemove.Where(serverId => runningUpdateTasks.ContainsKey(serverId)))
// remove the update tasks as they have completd
foreach (long serverId in serverTasksToRemove)
{
if (!runningUpdateTasks[serverId].tokenSource.Token.IsCancellationRequested)
{
runningUpdateTasks[serverId].tokenSource.Cancel();
}
runningUpdateTasks.Remove(serverId);
}
@ -254,33 +221,36 @@ namespace IW4MAdmin.Application
var serverIds = Servers.Select(s => s.EndPoint).Except(runningUpdateTasks.Select(r => r.Key)).ToList();
foreach (var server in Servers.Where(s => serverIds.Contains(s.EndPoint)))
{
var tokenSource = new CancellationTokenSource();
runningUpdateTasks.Add(server.EndPoint, (Task.Run(async () =>
runningUpdateTasks.Add(server.EndPoint, Task.Run(async () =>
{
try
{
if (runningUpdateTasks.ContainsKey(server.EndPoint))
await server.ProcessUpdatesAsync(_tokenSource.Token);
if (server.Throttled)
{
await server.ProcessUpdatesAsync(_tokenSource.Token)
.WithWaitCancellation(runningUpdateTasks[server.EndPoint].tokenSource.Token);
await Task.Delay((int)_throttleTimeout.TotalMilliseconds, _tokenSource.Token);
}
}
catch (Exception e)
{
using (LogContext.PushProperty("Server", server.ToString()))
{
_logger.LogError(e, "Failed to update status");
}
Logger.WriteWarning($"Failed to update status for {server}");
Logger.WriteDebug(e.GetExceptionInfo());
}
finally
{
server.IsInitialized = true;
}
}, tokenSource.Token), tokenSource, DateTime.Now));
}));
}
#if DEBUG
Logger.WriteDebug($"{runningUpdateTasks.Count} servers queued for stats updates");
ThreadPool.GetMaxThreads(out int workerThreads, out int n);
ThreadPool.GetAvailableThreads(out int availableThreads, out int m);
Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks");
#endif
try
{
await Task.Delay(ConfigHandler.Configuration().RConPollRate, _tokenSource.Token);
@ -302,15 +272,6 @@ namespace IW4MAdmin.Application
IsRunning = true;
ExternalIPAddress = await Utilities.GetExternalIP();
#region DATABASE
_logger.LogInformation("Beginning database migration sync");
Console.WriteLine(_translationLookup["MANAGER_MIGRATION_START"]);
await ContextSeed.Seed(_serviceProvider.GetRequiredService<IDatabaseContextFactory>(), _tokenSource.Token);
await DatabaseHousekeeping.RemoveOldRatings(_serviceProvider.GetRequiredService<IDatabaseContextFactory>(), _tokenSource.Token);
_logger.LogInformation("Finished database migration sync");
Console.WriteLine(_translationLookup["MANAGER_MIGRATION_END"]);
#endregion
#region PLUGINS
foreach (var plugin in Plugins)
{
@ -328,8 +289,8 @@ namespace IW4MAdmin.Application
catch (Exception ex)
{
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name));
_logger.LogError(ex, "Could not properly load plugin {plugin}", scriptPlugin.Name);
Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name));
Logger.WriteDebug(ex.Message);
}
};
}
@ -342,27 +303,32 @@ namespace IW4MAdmin.Application
catch (Exception ex)
{
_logger.LogError(ex, $"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}");
Logger.WriteError($"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}");
Logger.WriteDebug(ex.GetExceptionInfo());
}
}
#endregion
#region CONFIG
var config = ConfigHandler.Configuration();
// copy over default config if it doesn't exist
if (!_appConfig.Servers?.Any() ?? true)
if (config == null)
{
var defaultConfig = new BaseConfigurationHandler<DefaultSettings>("DefaultSettings").Configuration();
//ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate());
//var newConfig = ConfigHandler.Configuration();
var defaultConfig = new BaseConfigurationHandler<DefaultConfiguration>("DefaultSettings").Configuration();
ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate());
var newConfig = ConfigHandler.Configuration();
_appConfig.AutoMessages = defaultConfig.AutoMessages;
_appConfig.GlobalRules = defaultConfig.GlobalRules;
_appConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames;
newConfig.AutoMessages = defaultConfig.AutoMessages;
newConfig.GlobalRules = defaultConfig.GlobalRules;
newConfig.Maps = defaultConfig.Maps;
newConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames;
newConfig.QuickMessages = defaultConfig.QuickMessages;
//if (newConfig.Servers == null)
if (newConfig.Servers == null)
{
ConfigHandler.Set(_appConfig);
_appConfig.Servers = new ServerConfiguration[1];
ConfigHandler.Set(newConfig);
newConfig.Servers = new ServerConfiguration[1];
do
{
@ -377,41 +343,30 @@ namespace IW4MAdmin.Application
serverConfig.AddEventParser(parser);
}
_appConfig.Servers = _appConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray();
newConfig.Servers = newConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray();
} while (Utilities.PromptBool(_translationLookup["SETUP_SERVER_SAVE"]));
config = newConfig;
await ConfigHandler.Save();
}
}
else
{
if (string.IsNullOrEmpty(_appConfig.Id))
if (string.IsNullOrEmpty(config.Id))
{
_appConfig.Id = Guid.NewGuid().ToString();
config.Id = Guid.NewGuid().ToString();
await ConfigHandler.Save();
}
if (string.IsNullOrEmpty(_appConfig.WebfrontBindUrl))
if (string.IsNullOrEmpty(config.WebfrontBindUrl))
{
_appConfig.WebfrontBindUrl = "http://0.0.0.0:1624";
config.WebfrontBindUrl = "http://0.0.0.0:1624";
await ConfigHandler.Save();
}
#pragma warning disable 618
if (_appConfig.Maps != null)
{
_appConfig.Maps = null;
}
if (_appConfig.QuickMessages != null)
{
_appConfig.QuickMessages = null;
}
#pragma warning restore 618
var validator = new ApplicationConfigurationValidator();
var validationResult = validator.Validate(_appConfig);
var validationResult = validator.Validate(config);
if (!validationResult.IsValid)
{
@ -422,9 +377,9 @@ namespace IW4MAdmin.Application
};
}
foreach (var serverConfig in _appConfig.Servers)
foreach (var serverConfig in config.Servers)
{
ConfigurationMigration.ModifyLogPath020919(serverConfig);
Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig);
if (serverConfig.RConParserVersion == null || serverConfig.EventParserVersion == null)
{
@ -444,18 +399,26 @@ namespace IW4MAdmin.Application
}
}
if (_appConfig.Servers.Length == 0)
if (config.Servers.Length == 0)
{
throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
}
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(_appConfig.CustomParserEncoding) ? _appConfig.CustomParserEncoding : "windows-1252");
Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");
#endregion
#region DATABASE
using (var db = new DatabaseContext(GetApplicationSettings().Configuration()?.ConnectionString,
GetApplicationSettings().Configuration()?.DatabaseProvider))
{
await new ContextSeed(db).Seed();
}
#endregion
#region COMMANDS
if (await ClientSvc.HasOwnerAsync(_tokenSource.Token))
if (ClientSvc.GetOwners().Result.Count > 0)
{
_commands.RemoveAll(_cmd => _cmd.GetType() == typeof(OwnerCommand));
}
@ -477,8 +440,8 @@ namespace IW4MAdmin.Application
// this is because I want to store the command prefix in IW4MAdminSettings, but can't easily
// inject it to all the places that need it
cmdConfig.CommandPrefix = _appConfig.CommandPrefix;
cmdConfig.BroadcastCommandPrefix = _appConfig.BroadcastCommandPrefix;
cmdConfig.CommandPrefix = config.CommandPrefix;
cmdConfig.BroadcastCommandPrefix = config.BroadcastCommandPrefix;
foreach (var cmd in commandsToAddToConfig)
{
@ -509,7 +472,6 @@ namespace IW4MAdmin.Application
}
#endregion
Console.WriteLine(_translationLookup["MANAGER_COMMUNICATION_INFO"]);
await InitializeServers();
}
@ -525,20 +487,16 @@ namespace IW4MAdmin.Application
{
// todo: this might not always be an IW4MServer
var ServerInstance = _serverInstanceFactory.CreateServer(Conf, this) as IW4MServer;
using (LogContext.PushProperty("Server", ServerInstance.ToString()))
{
_logger.LogInformation("Beginning server communication initialization");
await ServerInstance.Initialize();
await ServerInstance.Initialize();
_servers.Add(ServerInstance);
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname.StripColors()));
_logger.LogInformation("Finishing initialization and now monitoring [{server}]", ServerInstance.Hostname, ServerInstance.ToString());
}
_servers.Add(ServerInstance);
Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname));
// add the start event for this server
var e = new GameEvent()
{
Type = EventType.Start,
Type = GameEvent.EventType.Start,
Data = $"{ServerInstance.GameName} started",
Owner = ServerInstance
};
@ -549,11 +507,13 @@ namespace IW4MAdmin.Application
catch (ServerException e)
{
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]"));
using (LogContext.PushProperty("Server", $"{Conf.IPAddress}:{Conf.Port}"))
Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]"));
if (e.GetType() == typeof(DvarException))
{
_logger.LogError(e, "Unexpected exception occurred during initialization");
Logger.WriteDebug($"{e.Message} {(e.GetType() == typeof(DvarException) ? $"({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})" : "")}");
}
lastException = e;
}
}
@ -588,10 +548,20 @@ namespace IW4MAdmin.Application
Stop();
}
[Obsolete]
public ObsoleteLogger GetLogger(long serverId)
public ILogger GetLogger(long serverId)
{
return _serviceProvider.GetRequiredService<ObsoleteLogger>();
if (_loggers.ContainsKey(serverId))
{
return _loggers[serverId];
}
else
{
var newLogger = new Logger($"IW4MAdmin-Server-{serverId}");
_loggers.Add(serverId, newLogger);
return newLogger;
}
}
public IList<MessageToken> GetMessageTokens()
@ -610,6 +580,11 @@ namespace IW4MAdmin.Application
return ClientSvc;
}
public AliasService GetAliasService()
{
return AliasSvc;
}
public PenaltyService GetPenaltyService()
{
return PenaltySvc;
@ -632,7 +607,7 @@ namespace IW4MAdmin.Application
public IRConParser GenerateDynamicRConParser(string name)
{
return new DynamicRConParser(_serviceProvider.GetRequiredService<ILogger<BaseRConParser>>(), _parserRegexFactory)
return new DynamicRConParser(_parserRegexFactory)
{
Name = name
};

View File

@ -4,9 +4,11 @@ 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%"
copy "%SolutionDir%SharedLibraryCore\%OutDir%*.deps.json" "%TargetDir%"
copy "%SolutionDir%SharedLibaryCore\%OutDir%*.deps.json" "%TargetDir%"
if not exist "%TargetDir%Plugins" (
echo "Making plugin dir"
@ -14,3 +16,12 @@ if not exist "%TargetDir%Plugins" (
)
xcopy /y "%SolutionDir%Build\Plugins" "%TargetDir%Plugins\"
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\"

View File

@ -1,78 +0,0 @@
using System;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models.Client;
using Data.Models.Misc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Commands
{
public class OfflineMessageCommand : Command
{
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
private const short MaxLength = 1024;
public OfflineMessageCommand(CommandConfiguration config, ITranslationLookup layout,
IDatabaseContextFactory contextFactory, ILogger<IDatabaseContextFactory> logger) : base(config, layout)
{
Name = "offlinemessage";
Description = _translationLookup["COMMANDS_OFFLINE_MESSAGE_DESC"];
Alias = "om";
Permission = EFClient.Permission.Moderator;
RequiresTarget = true;
_contextFactory = contextFactory;
_logger = logger;
}
public override async Task ExecuteAsync(GameEvent gameEvent)
{
if (gameEvent.Data.Length > MaxLength)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_TOO_LONG"].FormatExt(MaxLength));
return;
}
if (gameEvent.Target.ClientId == gameEvent.Origin.ClientId)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_SELF"].FormatExt(MaxLength));
return;
}
if (gameEvent.Target.IsIngame)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_INGAME"].FormatExt(gameEvent.Target.Name));
return;
}
await using var context = _contextFactory.CreateContext(enableTracking: false);
var server = await context.Servers.FirstAsync(srv => srv.EndPoint == gameEvent.Owner.ToString());
var newMessage = new EFInboxMessage()
{
SourceClientId = gameEvent.Origin.ClientId,
DestinationClientId = gameEvent.Target.ClientId,
ServerId = server.Id,
Message = gameEvent.Data,
};
try
{
context.Set<EFInboxMessage>().Add(newMessage);
await context.SaveChangesAsync();
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_SUCCESS"]);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not save offline message {@Message}", newMessage);
throw;
}
}
}
}

View File

@ -1,79 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using EFClient = Data.Models.Client.EFClient;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Commands
{
public class ReadMessageCommand : Command
{
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
public ReadMessageCommand(CommandConfiguration config, ITranslationLookup layout,
IDatabaseContextFactory contextFactory, ILogger<IDatabaseContextFactory> logger) : base(config, layout)
{
Name = "readmessage";
Description = _translationLookup["COMMANDS_READ_MESSAGE_DESC"];
Alias = "rm";
Permission = EFClient.Permission.Flagged;
_contextFactory = contextFactory;
_logger = logger;
}
public override async Task ExecuteAsync(GameEvent gameEvent)
{
try
{
await using var context = _contextFactory.CreateContext();
var inboxItems = await context.InboxMessages
.Include(message => message.SourceClient)
.ThenInclude(client => client.CurrentAlias)
.Where(message => message.DestinationClientId == gameEvent.Origin.ClientId)
.Where(message => !message.IsDelivered)
.ToListAsync();
if (!inboxItems.Any())
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_READ_MESSAGE_NONE"]);
return;
}
var index = 1;
foreach (var inboxItem in inboxItems)
{
await gameEvent.Origin.Tell(_translationLookup["COMMANDS_READ_MESSAGE_SUCCESS"]
.FormatExt($"{index}/{inboxItems.Count}", inboxItem.SourceClient.CurrentAlias.Name))
.WaitAsync();
foreach (var messageFragment in inboxItem.Message.FragmentMessageForDisplay())
{
await gameEvent.Origin.Tell(messageFragment).WaitAsync();
}
index++;
}
inboxItems.ForEach(item => { item.IsDelivered = true; });
context.UpdateRange(inboxItems);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
logger.LogError(ex, "Could not retrieve offline messages for {Client}", gameEvent.Origin.ToString());
throw;
}
}
}
}

View File

@ -1,49 +0,0 @@
{
"Serilog": {
"Using": [
"Serilog.Sinks.File"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"System": "Warning",
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Log/IW4MAdmin-Application.log",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Destructure": [
{
"Name": "ToMaximumDepth",
"Args": {
"maximumDestructuringDepth": 4
}
},
{
"Name": "ToMaximumStringLength",
"Args": {
"maximumStringLength": 1000
}
},
{
"Name": "ToMaximumCollectionCount",
"Args": {
"maximumCollectionCount": 24
}
}
]
}
}

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.Configuration
{
public class ScriptPluginConfiguration : Dictionary<string, Dictionary<string, object>>, IBaseConfiguration
{
public string Name() => nameof(ScriptPluginConfiguration);
public IBaseConfiguration Generate()
{
return new ScriptPluginConfiguration();
}
}
}

View File

@ -1,4 +1,4 @@
{
{
"AutoMessagePeriod": 60,
"AutoMessages": [
"This server uses ^5IW4M Admin v{{VERSION}} ^7get it at ^5raidmax.org/IW4MAdmin",
@ -16,13 +16,7 @@
"Keep grenade launcher use to a minimum",
"Balance teams at ALL times"
],
"DisallowedClientNames": [
"Unknown Soldier",
"VickNet",
"UnknownSoldier",
"CHEATER",
"Play77"
],
"DisallowedClientNames": [ "Unknown Soldier", "VickNet", "UnknownSoldier", "CHEATER", "Play77" ],
"QuickMessages": [
{
"Game": "IW4",
@ -169,18 +163,6 @@
"Alias": "Asylum",
"Name": "mp_asylum"
},
{
"Alias": "Banzai",
"Name": "mp_kwai"
},
{
"Alias": "Battery",
"Name": "mp_drum"
},
{
"Alias": "Breach",
"Name": "mp_bgate"
},
{
"Alias": "Castle",
"Name": "mp_castle"
@ -189,10 +171,6 @@
"Alias": "Cliffside",
"Name": "mp_shrine"
},
{
"Alias": "Corrosion",
"Name": "mp_stalingrad"
},
{
"Alias": "Courtyard",
"Name": "mp_courtyard"
@ -206,52 +184,60 @@
"Name": "mp_downfall"
},
{
"Alias": "Hangar",
"Alias": "Hanger",
"Name": "mp_hangar"
},
{
"Alias": "Knee Deep",
"Name": "mp_kneedeep"
},
{
"Alias": "Makin",
"Name": "mp_makin"
},
{
"Alias": "Makin Day",
"Name": "mp_makin_day"
},
{
"Alias": "Nightfire",
"Name": "mp_nachtfeuer"
},
{
"Alias": "Outskirts",
"Name": "mp_outskirts"
},
{
"Alias": "Revolution",
"Name": "mp_vodka"
},
{
"Alias": "Roundhouse",
"Name": "mp_roundhouse"
},
{
"Alias": "Seelow",
"Name": "mp_seelow"
"Alias": "Upheaval",
"Name": "mp_suburban"
},
{
"Alias": "Knee Deep",
"Name": "mp_kneedeep"
},
{
"Alias": "Nightfire",
"Name": "mp_nachtfeuer"
},
{
"Alias": "Station",
"Name": "mp_subway"
},
{
"Alias": "Banzai",
"Name": "mp_kwai"
},
{
"Alias": "Corrosion",
"Name": "mp_stalingrad"
},
{
"Alias": "Sub Pens",
"Name": "mp_docks"
},
{
"Alias": "Upheaval",
"Name": "mp_suburban"
"Alias": "Battery",
"Name": "mp_drum"
},
{
"Alias": "Breach",
"Name": "mp_bgate"
},
{
"Alias": "Revolution",
"Name": "mp_vodka"
}
]
},
@ -262,181 +248,225 @@
"Alias": "Rust",
"Name": "mp_rust"
},
{
"Alias": "Terminal",
"Name": "mp_terminal"
},
{
"Alias": "Crash",
"Name": "mp_crash"
},
{
"Alias": "Afghan",
"Name": "mp_afghan"
},
{
"Alias": "Derail",
"Name": "mp_derail"
},
{
"Alias": "Estate",
"Name": "mp_estate"
},
{
"Alias": "Favela",
"Name": "mp_favela"
},
{
"Alias": "Highrise",
"Name": "mp_highrise"
},
{
"Alias": "Invasion",
"Name": "mp_invasion"
},
{
"Alias": "Karachi",
"Name": "mp_checkpoint"
},
{
"Alias": "Quarry",
"Name": "mp_quarry"
},
{
"Alias": "Rundown",
"Name": "mp_rundown"
},
{
"Alias": "Scrapyard",
"Name": "mp_boneyard"
},
{
"Alias": "Skidrow",
"Name": "mp_nightshift"
},
{
"Alias": "Sub Base",
"Name": "mp_subbase"
},
{
"Alias": "Underpass",
"Name": "mp_underpass"
},
{
"Alias": "Wasteland",
"Name": "mp_brecourt"
},
{
"Alias": "Overgrown",
"Name": "mp_overgrown"
},
{
"Alias": "Strike",
"Name": "mp_strike"
},
{
"Alias": "Vacant",
"Name": "mp_vacant"
},
{
"Alias": "Carnival",
"Name": "mp_abandon"
},
{
"Alias": "Trailer Park",
"Name": "mp_trailerpark"
},
{
"Alias": "Fuel",
"Name": "mp_fuel2"
},
{
"Alias": "Storm",
"Name": "mp_storm"
},
{
"Alias": "Bailout",
"Name": "mp_complex"
},
{
"Alias": "Salvage",
"Name": "mp_compact"
},
{
"Alias": "Nuketown",
"Name": "mp_nuked"
},
{
"Alias": "Test map",
"Name": "iw4_credits"
},
{
"Alias": "Killhouse",
"Name": "mp_killhouse"
},
{
"Alias": "Bog",
"Name": "mp_bog_sh"
},
{
"Alias": "Freighter",
"Name": "mp_cargoship_sh"
},
{
"Alias": "Cargoship",
"Name": "mp_cargoship"
},
{
"Alias": "Shipment",
"Name": "mp_shipment"
},
{
"Alias": "Shipment - Long",
"Name": "mp_shipment_long"
},
{
"Alias": "Rust - Long",
"Name": "mp_rust_long"
},
{
"Alias": "Firing Range",
"Name": "mp_firingrange"
},
{
"Alias": "Chemical Plant",
"Name": "mp_storm_spring"
},
{
"Alias": "Tropical Favela",
"Name": "mp_fav_tropical"
},
{
"Alias": "Tropical Estate",
"Name": "mp_estate_tropical"
},
{
"Alias": "Tropical Crash",
"Name": "mp_crash_tropical"
},
{
"Alias": "Forgotten City",
"Name": "mp_bloc_sh"
},
{
"Alias": "Crossfire",
"Name": "mp_cross_fire"
},
{
"Alias": "Bloc",
"Name": "mp_bloc"
},
{
"Alias": "Oilrig",
"Name": "oilrig"
},
{
"Alias": "Village",
"Name": "co_hunted"
"Name": "Village",
"Alias": "co_hunted"
}
]
},
@ -489,7 +519,7 @@
},
{
"Alias": "Havana",
"Name": "mp_cairo"
"Name": "mp_cairo"
},
{
"Alias": "Hazard",
@ -695,10 +725,6 @@
{
"Alias": "Terminal",
"Name": "mp_terminal_cls"
},
{
"Alias": "Rust",
"Name": "mp_rust"
}
]
},
@ -858,596 +884,6 @@
"Name": "zm_transit"
}
]
},
{
"Game": "IW6",
"Maps": [
{
"Alias": "Prision Break",
"Name": "mp_prisonbreak"
},
{
"Alias": "Octane",
"Name": "mp_dart"
},
{
"Alias": "Tremor",
"Name": "mp_lonestar"
},
{
"Alias": "Freight",
"Name": "mp_frag"
},
{
"Alias": "Whiteout",
"Name": "mp_snow"
},
{
"Alias": "Stormfront",
"Name": "mp_fahrenheit"
},
{
"Alias": "Siege",
"Name": "mp_hashima"
},
{
"Alias": "Warhawk",
"Name": "mp_warhawk"
},
{
"Alias": "Sovereign",
"Name": "mp_sovereign"
},
{
"Alias": "Overload",
"Name": "mp_zebra"
},
{
"Alias": "Stonehaven",
"Name": "mp_skeleton"
},
{
"Alias": "Chasm",
"Name": "mp_chasm"
},
{
"Alias": "Flooded",
"Name": "mp_flooded"
},
{
"Alias": "Strikezone",
"Name": "mp_strikezone"
},
{
"Alias": "Free Fall",
"Name": "mp_descent_new"
},
{
"Alias": "Unearthed",
"Name": "mp_dome_ns"
},
{
"Alias": "Collision",
"Name": "mp_ca_impact"
},
{
"Alias": "Behemoth",
"Name": "mp_ca_behemoth"
},
{
"Alias": "Ruins",
"Name": "mp_battery3"
},
{
"Alias": "Pharaoh",
"Name": "mp_dig"
},
{
"Alias": "Favela",
"Name": "mp_favela_iw6"
},
{
"Alias": "Mutiny",
"Name": "mp_pirate"
},
{
"Alias": "Departed",
"Name": "mp_zulu"
},
{
"Alias": "Dynasty",
"Name": "mp_conflict"
},
{
"Alias": "Goldrush",
"Name": "mp_mine"
},
{
"Alias": "Showtime",
"Name": "mp_shipment_ns"
},
{
"Alias": "Subzero",
"Name": "mp_zerosub"
},
{
"Alias": "Ignition",
"Name": "mp_boneyard_ns"
},
{
"Alias": "Containment",
"Name": "mp_ca_red_river"
},
{
"Alias": "Bayview",
"Name": "mp_ca_rumble"
},
{
"Alias": "Fog",
"Name": "mp_swamp"
},
{
"Alias": "Point of Contact",
"Name": "mp_alien_town"
},
{
"Alias": "Nightfall",
"Name": "mp_alien_armory"
},
{
"Alias": "Mayday",
"Name": "mp_alien_beacon"
},
{
"Alias": "Awakening",
"Name": "mp_alien_dlc3"
},
{
"Alias": "Exodus",
"Name": "mp_alien_last"
}
]
},
{
"Game": "SHG1",
"Maps": [
{
"Alias": "Ascend",
"Name": "mp_refraction"
},
{
"Alias": "Bio Lab",
"Name": "mp_lab2"
},
{
"Alias": "Comeback",
"Name": "mp_comeback"
},
{
"Alias": "Defender",
"Name": "mp_laser2"
},
{
"Alias": "Detroit",
"Name": "mp_detroit"
},
{
"Alias": "Greenband",
"Name": "mp_greenband"
},
{
"Alias": "Horizon",
"Name": "mp_levity"
},
{
"Alias": "Instinct",
"Name": "mp_instinct"
},
{
"Alias": "Recovery",
"Name": "mp_recovery"
},
{
"Alias": "Retreat",
"Name": "mp_venus"
},
{
"Alias": "Riot",
"Name": "mp_prison"
},
{
"Alias": "Solar",
"Name": "mp_solar"
},
{
"Alias": "Terrace",
"Name": "mp_terrace"
},
{
"Alias": "Atlas Gorge",
"Name": "mp_dam"
},
{
"Alias": "Chop Shop",
"Name": "mp_spark"
},
{
"Alias": "Climate",
"Name": "mp_climate_3"
},
{
"Alias": "Compound",
"Name": "mp_sector17"
},
{
"Alias": "Core",
"Name": "mp_lost"
},
{
"Alias": "Drift",
"Name": "mp_torqued"
},
{
"Alias": "Fracture",
"Name": "mp_fracture"
},
{
"Alias": "Kremlin",
"Name": "mp_kremlin"
},
{
"Alias": "Overload",
"Name": "mp_lair"
},
{
"Alias": "Parliament",
"Name": "mp_bigben2"
},
{
"Alias": "Perplex",
"Name": "mp_perplex_1"
},
{
"Alias": "Quarantine",
"Name": "mp_liberty"
},
{
"Alias": "Sideshow",
"Name": "mp_clowntown3"
},
{
"Alias": "Site 244",
"Name": "mp_blackbox"
},
{
"Alias": "Skyrise",
"Name": "mp_highrise2"
},
{
"Alias": "Swarn",
"Name": "mp_seoul2"
},
{
"Alias": "Urban",
"Name": "mp_urban"
}
]
},
{
"Game": "CSGO",
"Maps": [
{
"Name": "ar_baggage",
"Alias": "Baggage"
},
{
"Name": "ar_dizzy",
"Alias": "Dizzy"
},
{
"Name": "ar_lunacy",
"Alias": "Lunacy"
},
{
"Name": "ar_monastery",
"Alias": "Monastery"
},
{
"Name": "ar_shoots",
"Alias": "Shoots"
},
{
"Name": "cs_agency",
"Alias": "Agency"
},
{
"Name": "cs_assault",
"Alias": "Assault"
},
{
"Name": "cs_italy",
"Alias": "Italy"
},
{
"Name": "cs_militia",
"Alias": "Militia"
},
{
"Name": "cs_office",
"Alias": "Office"
},
{
"Name": "de_ancient",
"Alias": "Ancient"
},
{
"Name": "de_bank",
"Alias": "Bank"
},
{
"Name": "de_cache",
"Alias": "Cache"
},
{
"Name": "de_calavera",
"Alias": "Calavera"
},
{
"Name": "de_canals",
"Alias": "Canals"
},
{
"Name": "de_cbble",
"Alias": "Cobblestone"
},
{
"Name": "de_dust2",
"Alias": "Dust II"
},
{
"Name": "de_grind",
"Alias": "Grind"
},
{
"Name": "de_inferno",
"Alias": "Inferno"
},
{
"Name": "de_lake",
"Alias": "Lake"
},
{
"Name": "de_mirage",
"Alias": "Mirage"
},
{
"Name": "de_mocha",
"Alias": "Mocha"
},
{
"Name": "de_nuke",
"Alias": "Nuke"
},
{
"Name": "de_overpass",
"Alias": "Overpass"
},
{
"Name": "de_pitstop",
"Alias": "Pitstop"
},
{
"Name": "de_safehouse",
"Alias": "Safehouse"
},
{
"Name": "de_shortdust",
"Alias": "Shortdust"
},
{
"Name": "de_shortnuke",
"Alias": "Shortnuke"
},
{
"Name": "de_stmarc",
"Alias": "St. Marc"
},
{
"Name": "de_sugarcane",
"Alias": "Sugarcane"
},
{
"Name": "de_train",
"Alias": "Train"
},
{
"Name": "de_vertigo",
"Alias": "Vertigo"
},
{
"Name": "dz_blacksite",
"Alias": "Blacksite"
},
{
"Name": "dz_frostbite",
"Alias": "Frostbite"
},
{
"Name": "dz_sirocco",
"Alias": "Sirocco"
}
]
}
],
"GameStrings": {
"IW4": {
"torso_upper": "Upper Torso",
"torso_lower": "Lower Torso",
"right_leg_upper": "Upper Right Leg",
"right_leg_lower": "Lower Right Leg",
"right_hand": "Right Hand",
"right_foot": "Right Foot",
"right_arm_upper": "Upper Right Arm",
"right_arm_lower": "Lower Right Arm",
"left_leg_upper": "Upper Left Leg",
"left_leg_lower": "Lower Left Leg",
"left_hand": "Left Hand",
"left_foot": "Left Foot",
"left_arm_upper": "Upper Left Arm",
"left_arm_lower": "Lower Left Arm",
"acog": "ACOG Sight",
"eotech": "Holographic Sight",
"fmj": "FMJ",
"gl": "Grenade Launcher",
"heartbeat": "Heartbeat Sensor",
"reflex": "Red Dot Sight",
"rof": "Rapid Fire",
"thermal": "Thermal",
"xmags": "Extended Mags",
"m4": "M4A1",
"m40a3": "M40A3",
"ak47": "AK-47",
"ak47classic": "AK-47 Classic",
"fn2000": "F2000",
"masada": "ACR",
"famas": "FAMAS",
"fal": "FAL",
"scar": "SCAR-H",
"tavor": "TAR-21",
"m16": "M16A4",
"mp5k": "MP5K",
"ump45": "UMP45",
"kriss": "Vector",
"uzi": "Mini-Uzi",
"rpd": "RPD",
"sa80": "L86 LSW",
"mg4": "MG4",
"aug": "AUG HBAR",
"cheytac": "Intervention",
"barrett": "Barrett .50cal",
"wa2000": "WA2000",
"m21": "M21 EBR",
"pp2000": "PP2000",
"glock": "G18",
"beretta": "M93 Raffica",
"tmp": "TMP",
"spas12": "SPAS-12",
"aa12": "AA-12",
"model1887": "Model 1887",
"usp": "USP .45",
"coltanaconda": ".44 Magnum",
"deserteagle": "Desert Eagle",
"deserteaglegold": "Desert Eagle Gold",
"at4": "AT4-HS",
"m79": "Thumper",
"rpg": "RPG-7",
"concussion": "Stun",
"throwingknife": "Throwing Knife",
"ffar": "Airstrike",
"pavelow": "Pave Low",
"cobra": "Attack Helicopter",
"ac130": "AC-130",
"remotemissile": "Predator Missile",
"artillery": "Precision Airstrike",
"player": "",
"attach": ""
},
"IW3": {
"torso_upper": "Upper Torso",
"torso_lower": "Lower Torso",
"right_leg_upper": "Upper Right Leg",
"right_leg_lower": "Lower Right Leg",
"right_hand": "Right Hand",
"right_foot": "Right Foot",
"right_arm_upper": "Upper Right Arm",
"right_arm_lower": "Lower Right Arm",
"left_leg_upper": "Upper Left Leg",
"left_leg_lower": "Lower Left Leg",
"left_hand": "Left Hand",
"left_foot": "Left Foot",
"left_arm_upper": "Upper Left Arm",
"left_arm_lower": "Lower Left Arm",
"acog": "ACOG Sight",
"gl": "Grenade Launcher",
"reflex": "Red Dot Sight",
"grip": "Grip",
"m4": "M4 Carbine",
"m40a3": "M40A3",
"ak47": "AK-47",
"ak74u": "AK-74u",
"rpg": "RPG-7",
"deserteagle": "Desert Eagle",
"deserteaglegold": "Desert Eagle Gold",
"m16": "M16A4",
"g36c": "G36C",
"uzi": "Mini-Uzi",
"m60e4": "M60E4",
"mp5": "MP5",
"barrett": "Barrett .50cal",
"mp44": "MP44",
"remington700": "R700",
"rpd": "RDP",
"saw": " M249 SAW",
"usp": "USP .45",
"winchester1200": "W1200",
"concussion": "Stun",
"melee": "Knife",
"Frag" : "Grenade",
"airstrike": "Airstrike",
"helicopter": "Attack Helicopter",
"player": "",
"attach": ""
},
"T4": {
"torso_upper": "Upper Torso",
"torso_lower": "Lower Torso",
"right_leg_upper": "Upper Right Leg",
"right_leg_lower": "Lower Right Leg",
"right_hand": "Right Hand",
"right_foot": "Right Foot",
"right_arm_upper": "Upper Right Arm",
"right_arm_lower": "Lower Right Arm",
"left_leg_upper": "Upper Left Leg",
"left_leg_lower": "Lower Left Leg",
"left_hand": "Left Hand",
"left_foot": "Left Foot",
"left_arm_upper": "Upper Left Arm",
"left_arm_lower": "Lower Left Arm",
"gl": "Rifle Grenade",
"bigammo": "Round Drum",
"scoped": "Sniper Scope",
"telescopic": "Telescopic Sight",
"aperture": "Aperture Sight",
"flash": "Flash Hider",
"silenced": "Silencer",
"molotov": "Molotov Cocktail",
"sticky": "N° 74 ST",
"m2": "M2 Flamethrower",
"artillery": "Artillery Strike",
"dog": "Attack Dogs",
"colt": "Colt M1911",
"357magnum": ".357 Magnum",
"walther": "Walther P38",
"tokarev": "Tokarev TT-33",
"shotgun": "M1897 Trench Gun",
"doublebarreledshotgun": "Double-Barreled Shotgun",
"mp40": "MP40",
"type100smg": "Type 100",
"ppsh": "PPSh-41",
"svt40": "SVT-40",
"gewehr43": "Gewehr 43",
"m1garand": "M1 Garand",
"stg44": "STG-44",
"m1carbine": "M1A1 Carbine",
"type99lmg": "Type 99",
"bar": "BAR",
"dp28": "DP-28",
"mg42": "MG42",
"fg42": "FG42",
"30cal": "Browning M1919",
"type99rifle": "Arisaka",
"mosinrifle": "Mosin-Nagant",
"ptrs41":"PTRS-41"
}
}
]
}

View File

@ -5,10 +5,7 @@ using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using Data.Models;
using Microsoft.Extensions.Logging;
using static SharedLibraryCore.Server;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.EventParsers
{
@ -17,8 +14,6 @@ namespace IW4MAdmin.Application.EventParsers
private readonly Dictionary<string, (string, Func<string, IEventParserConfiguration, GameEvent, GameEvent>)> _customEventRegistrations;
private readonly ILogger _logger;
private readonly ApplicationConfiguration _appConfig;
private readonly Dictionary<ParserRegex, GameEvent.EventType> _regexMap;
private readonly Dictionary<string, GameEvent.EventType> _eventTypeMap;
public BaseEventParser(IParserRegexFactory parserRegexFactory, ILogger logger, ApplicationConfiguration appConfig)
{
@ -80,28 +75,7 @@ namespace IW4MAdmin.Application.EventParsers
Configuration.Kill.AddMapping(ParserRegex.GroupType.MeansOfDeath, 12);
Configuration.Kill.AddMapping(ParserRegex.GroupType.HitLocation, 13);
Configuration.MapChange.Pattern = @".*InitGame.*";
Configuration.MapEnd.Pattern = @".*(?:ExitLevel|ShutdownGame).*";
Configuration.Time.Pattern = @"^ *(([0-9]+):([0-9]+) |^[0-9]+ )";
_regexMap = new Dictionary<ParserRegex, GameEvent.EventType>
{
{Configuration.Say, GameEvent.EventType.Say},
{Configuration.Kill, GameEvent.EventType.Kill},
{Configuration.MapChange, GameEvent.EventType.MapChange},
{Configuration.MapEnd, GameEvent.EventType.MapEnd}
};
_eventTypeMap = new Dictionary<string, GameEvent.EventType>
{
{"say", GameEvent.EventType.Say},
{"sayteam", GameEvent.EventType.Say},
{"K", GameEvent.EventType.Kill},
{"D", GameEvent.EventType.Damage},
{"J", GameEvent.EventType.PreConnect},
{"Q", GameEvent.EventType.PreDisconnect},
};
}
public IEventParserConfiguration Configuration { get; set; }
@ -114,79 +88,47 @@ namespace IW4MAdmin.Application.EventParsers
public string Name { get; set; } = "Call of Duty";
private (GameEvent.EventType type, string eventKey) GetEventTypeFromLine(string logLine)
{
var lineSplit = logLine.Split(';');
if (lineSplit.Length > 1)
{
var type = lineSplit[0];
return _eventTypeMap.ContainsKey(type) ? (_eventTypeMap[type], type): (GameEvent.EventType.Unknown, lineSplit[0]);
}
foreach (var (key, value) in _regexMap)
{
var result = key.PatternMatcher.Match(logLine);
if (result.Success)
{
return (value, null);
}
}
return (GameEvent.EventType.Unknown, null);
}
public virtual GameEvent GenerateGameEvent(string logLine)
{
var timeMatch = Configuration.Time.PatternMatcher.Match(logLine);
var gameTime = 0L;
int gameTime = 0;
if (timeMatch.Success)
{
if (timeMatch.Values[0].Contains(":"))
{
gameTime = timeMatch
.Values
.Skip(2)
// this converts the timestamp into seconds passed
.Select((value, index) => long.Parse(value.ToString()) * (index == 0 ? 60 : 1))
.Sum();
}
else
{
gameTime = long.Parse(timeMatch.Values[0]);
}
gameTime = timeMatch
.Values
.Skip(2)
// this converts the timestamp into seconds passed
.Select((_value, index) => int.Parse(_value.ToString()) * (index == 0 ? 60 : 1))
.Sum();
// we want to strip the time from the log line
logLine = logLine.Substring(timeMatch.Values.First().Length).Trim();
logLine = logLine.Substring(timeMatch.Values.First().Length);
}
var eventParseResult = GetEventTypeFromLine(logLine);
var eventType = eventParseResult.type;
string[] lineSplit = logLine.Split(';');
string eventType = lineSplit[0];
_logger.LogDebug(logLine);
if (eventType == GameEvent.EventType.Say)
if (eventType == "say" || eventType == "sayteam")
{
var matchResult = Configuration.Say.PatternMatcher.Match(logLine);
if (matchResult.Success)
{
var message = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.Message]]
string message = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.Message]]
.ToString()
.Replace("\x15", "")
.Trim();
if (message.Length > 0)
{
var originIdString = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var originName = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginName]];
string originIdString = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string originName = matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginName]].ToString();
var originId = originIdString.IsBotGuid() ?
long originId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle);
var clientNumber = int.Parse(matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
int clientNumber = int.Parse(matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
if (message.StartsWith(_appConfig.CommandPrefix) || message.StartsWith(_appConfig.BroadcastCommandPrefix))
{
@ -218,26 +160,26 @@ namespace IW4MAdmin.Application.EventParsers
}
}
if (eventType == GameEvent.EventType.Kill)
if (eventType == "K")
{
var match = Configuration.Kill.PatternMatcher.Match(logLine);
if (match.Success)
{
var originIdString = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var targetIdString = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]];
var originName = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginName]];
var targetName = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetName]];
string originIdString = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string targetIdString = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString();
string originName = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginName]].ToString();
string targetName = match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetName]].ToString();
var originId = originIdString.IsBotGuid() ?
long originId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle, Utilities.WORLD_ID);
var targetId = targetIdString.IsBotGuid() ?
long targetId = targetIdString.IsBotGuid() ?
targetName.GenerateGuidFromString() :
targetIdString.ConvertGuidToLong(Configuration.GuidNumberStyle, Utilities.WORLD_ID);
var originClientNumber = int.Parse(match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
var targetClientNumber = int.Parse(match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetClientNumber]]);
int originClientNumber = int.Parse(match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
int targetClientNumber = int.Parse(match.Values[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetClientNumber]]);
return new GameEvent()
{
@ -252,26 +194,26 @@ namespace IW4MAdmin.Application.EventParsers
}
}
if (eventType == GameEvent.EventType.Damage)
if (eventType == "D")
{
var match = Configuration.Damage.PatternMatcher.Match(logLine);
if (match.Success)
{
var originIdString = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var targetIdString = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]];
var originName = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginName]];
var targetName = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetName]];
string originIdString = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string targetIdString = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString();
string originName = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginName]].ToString();
string targetName = match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetName]].ToString();
var originId = originIdString.IsBotGuid() ?
long originId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle, Utilities.WORLD_ID);
var targetId = targetIdString.IsBotGuid() ?
long targetId = targetIdString.IsBotGuid() ?
targetName.GenerateGuidFromString() :
targetIdString.ConvertGuidToLong(Configuration.GuidNumberStyle, Utilities.WORLD_ID);
var originClientNumber = int.Parse(match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
var targetClientNumber = int.Parse(match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetClientNumber]]);
int originClientNumber = int.Parse(match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
int targetClientNumber = int.Parse(match.Values[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetClientNumber]]);
return new GameEvent()
{
@ -286,16 +228,16 @@ namespace IW4MAdmin.Application.EventParsers
}
}
if (eventType == GameEvent.EventType.PreConnect)
if (eventType == "J")
{
var match = Configuration.Join.PatternMatcher.Match(logLine);
if (match.Success)
{
var originIdString = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var originName = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginName]];
string originIdString = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string originName = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginName]].ToString();
var networkId = originIdString.IsBotGuid() ?
long networkId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle);
@ -307,10 +249,10 @@ namespace IW4MAdmin.Application.EventParsers
{
CurrentAlias = new EFAlias()
{
Name = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginName]].TrimNewLine(),
Name = match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginName]].ToString().TrimNewLine(),
},
NetworkId = networkId,
ClientNumber = Convert.ToInt32(match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]),
ClientNumber = Convert.ToInt32(match.Values[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
State = EFClient.ClientState.Connecting,
},
Extra = originIdString,
@ -322,16 +264,16 @@ namespace IW4MAdmin.Application.EventParsers
}
}
if (eventType == GameEvent.EventType.PreDisconnect)
if (eventType == "Q")
{
var match = Configuration.Quit.PatternMatcher.Match(logLine);
if (match.Success)
{
var originIdString = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginNetworkId]];
var originName = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginName]];
string originIdString = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string originName = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginName]].ToString();
var networkId = originIdString.IsBotGuid() ?
long networkId = originIdString.IsBotGuid() ?
originName.GenerateGuidFromString() :
originIdString.ConvertGuidToLong(Configuration.GuidNumberStyle);
@ -343,10 +285,10 @@ namespace IW4MAdmin.Application.EventParsers
{
CurrentAlias = new EFAlias()
{
Name = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginName]].TrimNewLine()
Name = match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginName]].ToString().TrimNewLine()
},
NetworkId = networkId,
ClientNumber = Convert.ToInt32(match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]),
ClientNumber = Convert.ToInt32(match.Values[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
State = EFClient.ClientState.Disconnecting
},
RequiredEntity = GameEvent.EventRequiredEntity.None,
@ -357,7 +299,7 @@ namespace IW4MAdmin.Application.EventParsers
}
}
if (eventType == GameEvent.EventType.MapEnd)
if (eventType.Contains("ExitLevel"))
{
return new GameEvent()
{
@ -371,9 +313,9 @@ namespace IW4MAdmin.Application.EventParsers
};
}
if (eventType == GameEvent.EventType.MapChange)
if (eventType.Contains("InitGame"))
{
var dump = logLine.Replace("InitGame: ", "");
string dump = eventType.Replace("InitGame: ", "");
return new GameEvent()
{
@ -388,37 +330,26 @@ namespace IW4MAdmin.Application.EventParsers
};
}
if (eventParseResult.eventKey == null || !_customEventRegistrations.ContainsKey(eventParseResult.eventKey))
if (_customEventRegistrations.ContainsKey(eventType))
{
return new GameEvent()
var eventModifier = _customEventRegistrations[eventType];
try
{
Type = GameEvent.EventType.Unknown,
Data = logLine,
Origin = Utilities.IW4MAdminClient(),
Target = Utilities.IW4MAdminClient(),
RequiredEntity = GameEvent.EventRequiredEntity.None,
GameTime = gameTime,
Source = GameEvent.EventSource.Log
};
}
return eventModifier.Item2(logLine, Configuration, new GameEvent()
{
Type = GameEvent.EventType.Other,
Data = logLine,
Subtype = eventModifier.Item1,
GameTime = gameTime,
Source = GameEvent.EventSource.Log
});
}
var eventModifier = _customEventRegistrations[eventParseResult.eventKey];
try
{
return eventModifier.Item2(logLine, Configuration, new GameEvent()
catch (Exception e)
{
Type = GameEvent.EventType.Other,
Data = logLine,
Subtype = eventModifier.Item1,
GameTime = gameTime,
Source = GameEvent.EventSource.Log
});
}
catch (Exception e)
{
_logger.LogError(e, "Could not handle custom event generation");
_logger.WriteWarning($"Could not handle custom event generation - {e.GetExceptionInfo()}");
}
}
return new GameEvent()

View File

@ -1,6 +1,5 @@
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.EventParsers
{

View File

@ -1,6 +1,5 @@
using SharedLibraryCore.Interfaces;
using System.Globalization;
using SharedLibraryCore;
namespace IW4MAdmin.Application.EventParsers
{
@ -18,8 +17,6 @@ namespace IW4MAdmin.Application.EventParsers
public ParserRegex Damage { get; set; }
public ParserRegex Action { get; set; }
public ParserRegex Time { get; set; }
public ParserRegex MapChange { get; set; }
public ParserRegex MapEnd { get; set; }
public NumberStyles GuidNumberStyle { get; set; } = NumberStyles.HexNumber;
public DynamicEventParserConfiguration(IParserRegexFactory parserRegexFactory)
@ -31,8 +28,6 @@ namespace IW4MAdmin.Application.EventParsers
Damage = parserRegexFactory.CreateParserRegex();
Action = parserRegexFactory.CreateParserRegex();
Time = parserRegexFactory.CreateParserRegex();
MapChange = parserRegexFactory.CreateParserRegex();
MapEnd = parserRegexFactory.CreateParserRegex();
}
}
}

View File

@ -1,104 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using Data.MigrationContext;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using ILogger = Serilog.ILogger;
namespace IW4MAdmin.Application.Extensions
{
public static class StartupExtensions
{
private static ILogger _defaultLogger = null;
public static IServiceCollection AddBaseLogger(this IServiceCollection services,
ApplicationConfiguration appConfig)
{
if (_defaultLogger == null)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile(Path.Join(Utilities.OperatingDirectory, "Configuration", "LoggingConfiguration.json"))
.Build();
var loggerConfig = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning);
if (Utilities.IsDevelopment)
{
loggerConfig = loggerConfig.WriteTo.Console(
outputTemplate:
"[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Debug();
}
_defaultLogger = loggerConfig.CreateLogger();
}
services.AddLogging(builder => builder.AddSerilog(_defaultLogger, dispose: true));
services.AddSingleton(new LoggerFactory()
.AddSerilog(_defaultLogger, true));
return services;
}
public static IServiceCollection AddDatabaseContextOptions(this IServiceCollection services,
ApplicationConfiguration appConfig)
{
var activeProvider = appConfig.DatabaseProvider?.ToLower();
if (string.IsNullOrEmpty(appConfig.ConnectionString) || activeProvider == "sqlite")
{
var currentPath = Utilities.OperatingDirectory;
currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? $"{Path.DirectorySeparatorChar}{currentPath}"
: currentPath;
var connectionStringBuilder = new SqliteConnectionStringBuilder
{DataSource = Path.Join(currentPath, "Database", "Database.db")};
var connectionString = connectionStringBuilder.ToString();
services.AddSingleton(sp => (DbContextOptions) new DbContextOptionsBuilder<SqliteDatabaseContext>()
.UseSqlite(connectionString)
.UseLoggerFactory(sp.GetRequiredService<ILoggerFactory>())
.EnableSensitiveDataLogging().Options);
return services;
}
switch (activeProvider)
{
case "mysql":
var appendTimeout = !appConfig.ConnectionString.Contains("default command timeout",
StringComparison.InvariantCultureIgnoreCase);
services.AddSingleton(sp => (DbContextOptions) new DbContextOptionsBuilder<MySqlDatabaseContext>()
.UseMySql(appConfig.ConnectionString + (appendTimeout ? ";default command timeout=0" : ""),
mysqlOptions => mysqlOptions.EnableRetryOnFailure())
.UseLoggerFactory(sp.GetRequiredService<ILoggerFactory>()).Options);
return services;
case "postgresql":
appendTimeout = !appConfig.ConnectionString.Contains("Command Timeout",
StringComparison.InvariantCultureIgnoreCase);
services.AddSingleton(sp =>
(DbContextOptions) new DbContextOptionsBuilder<PostgresqlDatabaseContext>()
.UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""),
postgresqlOptions =>
{
postgresqlOptions.EnableRetryOnFailure();
postgresqlOptions.SetPostgresVersion(new Version("9.4"));
})
.UseLoggerFactory(sp.GetRequiredService<ILoggerFactory>()).Options);
return services;
default:
throw new ArgumentException($"No context available for {appConfig.DatabaseProvider}");
}
}
}
}

View File

@ -1,9 +1,5 @@
using System;
using Data.Abstractions;
using Data.Context;
using Data.MigrationContext;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.Factories
{
@ -12,15 +8,6 @@ namespace IW4MAdmin.Application.Factories
/// </summary>
public class DatabaseContextFactory : IDatabaseContextFactory
{
private readonly DbContextOptions _contextOptions;
private readonly string _activeProvider;
public DatabaseContextFactory(ApplicationConfiguration appConfig, DbContextOptions contextOptions)
{
_contextOptions = contextOptions;
_activeProvider = appConfig.DatabaseProvider?.ToLower();
}
/// <summary>
/// creates a new database context
/// </summary>
@ -28,35 +15,7 @@ namespace IW4MAdmin.Application.Factories
/// <returns></returns>
public DatabaseContext CreateContext(bool? enableTracking = true)
{
var context = BuildContext();
enableTracking ??= true;
if (enableTracking.Value)
{
context.ChangeTracker.AutoDetectChangesEnabled = true;
context.ChangeTracker.LazyLoadingEnabled = true;
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;
}
else
{
context.ChangeTracker.AutoDetectChangesEnabled = false;
context.ChangeTracker.LazyLoadingEnabled = false;
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
return context;
}
private DatabaseContext BuildContext()
{
return _activeProvider switch
{
"sqlite" => new SqliteDatabaseContext(_contextOptions),
"mysql" => new MySqlDatabaseContext(_contextOptions),
"postgresql" => new PostgresqlDatabaseContext(_contextOptions),
_ => throw new ArgumentException($"No context found for {_activeProvider}")
};
return enableTracking.HasValue ? new DatabaseContext(disableTracking: !enableTracking.Value) : new DatabaseContext();
}
}
}

View File

@ -2,7 +2,6 @@
using Microsoft.Extensions.DependencyInjection;
using SharedLibraryCore.Interfaces;
using System;
using Microsoft.Extensions.Logging;
namespace IW4MAdmin.Application.Factories
{
@ -20,12 +19,12 @@ namespace IW4MAdmin.Application.Factories
var baseUri = logUris[0];
if (baseUri.Scheme == Uri.UriSchemeHttp)
{
return new GameLogReaderHttp(logUris, eventParser, _serviceProvider.GetRequiredService<ILogger<GameLogReaderHttp>>());
return new GameLogReaderHttp(logUris, eventParser, _serviceProvider.GetRequiredService<ILogger>());
}
else if (baseUri.Scheme == Uri.UriSchemeFile)
{
return new GameLogReader(baseUri.LocalPath, eventParser, _serviceProvider.GetRequiredService<ILogger<GameLogReader>>());
return new GameLogReader(baseUri.LocalPath, eventParser, _serviceProvider.GetRequiredService<ILogger>());
}
throw new NotImplementedException($"No log reader implemented for Uri scheme \"{baseUri.Scheme}\"");

View File

@ -1,10 +1,7 @@
using System;
using Data.Abstractions;
using Data.Models.Server;
using Microsoft.Extensions.DependencyInjection;
using SharedLibraryCore;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using System.Collections;
namespace IW4MAdmin.Application.Factories
{
@ -14,21 +11,21 @@ namespace IW4MAdmin.Application.Factories
internal class GameServerInstanceFactory : IGameServerInstanceFactory
{
private readonly ITranslationLookup _translationLookup;
private readonly IRConConnectionFactory _rconConnectionFactory;
private readonly IGameLogReaderFactory _gameLogReaderFactory;
private readonly IMetaService _metaService;
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// base constructor
/// </summary>
/// <param name="translationLookup"></param>
/// <param name="rconConnectionFactory"></param>
public GameServerInstanceFactory(ITranslationLookup translationLookup,
IMetaService metaService,
IServiceProvider serviceProvider)
public GameServerInstanceFactory(ITranslationLookup translationLookup, IRConConnectionFactory rconConnectionFactory, IGameLogReaderFactory gameLogReaderFactory, IMetaService metaService)
{
_translationLookup = translationLookup;
_rconConnectionFactory = rconConnectionFactory;
_gameLogReaderFactory = gameLogReaderFactory;
_metaService = metaService;
_serviceProvider = serviceProvider;
}
/// <summary>
@ -39,10 +36,7 @@ namespace IW4MAdmin.Application.Factories
/// <returns></returns>
public Server CreateServer(ServerConfiguration config, IManager manager)
{
return new IW4MServer(config,
_serviceProvider.GetRequiredService<CommandConfiguration>(), _translationLookup, _metaService,
_serviceProvider, _serviceProvider.GetRequiredService<IClientNoticeMessageFormatter>(),
_serviceProvider.GetRequiredService<ILookupCache<EFServer>>());
return new IW4MServer(manager, config, _translationLookup, _rconConnectionFactory, _gameLogReaderFactory, _metaService);
}
}
}

View File

@ -1,12 +1,6 @@
using System;
using System.Net;
using IW4MAdmin.Application.RCon;
using SharedLibraryCore.Interfaces;
using System.Text;
using Integrations.Cod;
using Integrations.Source;
using Integrations.Source.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace IW4MAdmin.Application.Factories
{
@ -15,29 +9,28 @@ namespace IW4MAdmin.Application.Factories
/// </summary>
internal class RConConnectionFactory : IRConConnectionFactory
{
private static readonly Encoding GameEncoding = Encoding.GetEncoding("windows-1252");
private readonly IServiceProvider _serviceProvider;
private static readonly Encoding gameEncoding = Encoding.GetEncoding("windows-1252");
private readonly ILogger _logger;
/// <summary>
/// Base constructor
/// </summary>
/// <param name="logger"></param>
public RConConnectionFactory(IServiceProvider serviceProvider)
public RConConnectionFactory(ILogger logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
/// <inheritdoc/>
public IRConConnection CreateConnection(IPEndPoint ipEndpoint, string password, string rconEngine)
/// <summary>
/// creates a new rcon connection instance
/// </summary>
/// <param name="ipAddress">ip address of the server</param>
/// <param name="port">port of the server</param>
/// <param name="password">rcon password of the server</param>
/// <returns></returns>
public IRConConnection CreateConnection(string ipAddress, int port, string password)
{
return rconEngine switch
{
"COD" => new CodRConConnection(ipEndpoint, password,
_serviceProvider.GetRequiredService<ILogger<CodRConConnection>>(), GameEncoding),
"Source" => new SourceRConConnection(_serviceProvider.GetRequiredService<ILogger<SourceRConConnection>>(),
_serviceProvider.GetRequiredService<IRConClientFactory>(), ipEndpoint, password),
_ => throw new ArgumentException($"No supported RCon engine available for '{rconEngine}'")
};
return new RConConnection(ipAddress, port, password, _logger, gameEncoding);
}
}
}

View File

@ -6,9 +6,7 @@ using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using Data.Models.Client;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using static SharedLibraryCore.Database.Models.EFClient;
namespace IW4MAdmin.Application.Factories
{
@ -17,30 +15,26 @@ namespace IW4MAdmin.Application.Factories
/// </summary>
public class ScriptCommandFactory : IScriptCommandFactory
{
private readonly CommandConfiguration _config;
private CommandConfiguration _config;
private readonly ITranslationLookup _transLookup;
private readonly IServiceProvider _serviceProvider;
public ScriptCommandFactory(CommandConfiguration config, ITranslationLookup transLookup, IServiceProvider serviceProvider)
public ScriptCommandFactory(CommandConfiguration config, ITranslationLookup transLookup)
{
_config = config;
_transLookup = transLookup;
_serviceProvider = serviceProvider;
}
/// <inheritdoc/>
public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission,
bool isTargetRequired, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction)
public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, bool isTargetRequired, IEnumerable<(string, bool)> args, Action<GameEvent> executeAction)
{
var permissionEnum = Enum.Parse<EFClient.Permission>(permission);
var permissionEnum = Enum.Parse<Permission>(permission);
var argsArray = args.Select(_arg => new CommandArgument
{
Name = _arg.Item1,
Required = _arg.Item2
}).ToArray();
return new ScriptCommand(name, alias, description, isTargetRequired, permissionEnum, argsArray, executeAction,
_config, _transLookup, _serviceProvider.GetRequiredService<ILogger<ScriptCommand>>());
return new ScriptCommand(name, alias, description, isTargetRequired, permissionEnum, argsArray, executeAction, _config, _transLookup);
}
}
}

View File

@ -1,19 +1,19 @@
using IW4MAdmin.Application.Misc;
using Newtonsoft.Json;
using SharedLibraryCore;
using SharedLibraryCore.Events;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application
{
public class GameEventHandler : IEventHandler
{
private readonly EventLog _eventLog;
private readonly ILogger _logger;
private readonly IEventPublisher _eventPublisher;
private static readonly GameEvent.EventType[] overrideEvents = new[]
{
GameEvent.EventType.Connect,
@ -22,25 +22,34 @@ namespace IW4MAdmin.Application
GameEvent.EventType.Stop
};
public GameEventHandler(ILogger<GameEventHandler> logger, IEventPublisher eventPublisher)
public GameEventHandler()
{
_eventLog = new EventLog();
_logger = logger;
_eventPublisher = eventPublisher;
}
public void HandleEvent(IManager manager, GameEvent gameEvent)
{
#if DEBUG
ThreadPool.GetMaxThreads(out int workerThreads, out int n);
ThreadPool.GetAvailableThreads(out int availableThreads, out int m);
gameEvent.Owner.Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks");
#endif
if (manager.IsRunning || overrideEvents.Contains(gameEvent.Type))
{
#if DEBUG
gameEvent.Owner.Logger.WriteDebug($"Adding event with id {gameEvent.Id}");
#endif
EventApi.OnGameEvent(gameEvent);
_eventPublisher.Publish(gameEvent);
Task.Factory.StartNew(() => manager.ExecuteEvent(gameEvent));
}
#if DEBUG
else
{
_logger.LogDebug("Skipping event as we're shutting down {eventId}", gameEvent.Id);
gameEvent.Owner.Logger.WriteDebug($"Skipping event as we're shutting down {gameEvent.Id}");
}
#endif
}
}
}

View File

@ -3,9 +3,6 @@ using SharedLibraryCore.Interfaces;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.IO
{
@ -15,14 +12,12 @@ namespace IW4MAdmin.Application.IO
private readonly Server _server;
private readonly IGameLogReader _reader;
private readonly bool _ignoreBots;
private readonly ILogger _logger;
public GameLogEventDetection(ILogger<GameLogEventDetection> logger, IW4MServer server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory)
public GameLogEventDetection(Server server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory)
{
_reader = gameLogReaderFactory.CreateGameLogReader(gameLogUris, server.EventParser);
_server = server;
_ignoreBots = server?.Manager.GetApplicationSettings().Configuration().IgnoreBots ?? false;
_logger = logger;
}
public async Task PollForChanges()
@ -38,17 +33,15 @@ namespace IW4MAdmin.Application.IO
catch (Exception e)
{
using(LogContext.PushProperty("Server", _server.ToString()))
{
_logger.LogError(e, "Failed to update log event for {endpoint}", _server.EndPoint);
}
_server.Logger.WriteWarning($"Failed to update log event for {_server.EndPoint}");
_server.Logger.WriteDebug(e.GetExceptionInfo());
}
}
await Task.Delay(_reader.UpdateInterval, _server.Manager.CancellationToken);
}
_logger.LogDebug("Stopped polling for changes");
_server.Logger.WriteDebug("Stopped polling for changes");
}
public async Task UpdateLogEvents()
@ -75,6 +68,9 @@ namespace IW4MAdmin.Application.IO
{
try
{
#if DEBUG
_server.Logger.WriteVerbose(gameEvent.Data);
#endif
gameEvent.Owner = _server;
// we don't want to add the event if ignoreBots is on and the event comes from a bot
@ -106,14 +102,10 @@ namespace IW4MAdmin.Application.IO
catch (InvalidOperationException)
{
if (_ignoreBots)
if (!_ignoreBots)
{
continue;
}
using(LogContext.PushProperty("Server", _server.ToString()))
{
_logger.LogError("Could not find client in client list when parsing event line {data}", gameEvent.Data);
_server.Logger.WriteWarning("Could not find client in client list when parsing event line");
_server.Logger.WriteDebug(gameEvent.Data);
}
}
}

View File

@ -6,8 +6,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.IO
{
@ -21,7 +19,7 @@ namespace IW4MAdmin.Application.IO
public int UpdateInterval => 300;
public GameLogReader(string logFile, IEventParser parser, ILogger<GameLogReader> logger)
public GameLogReader(string logFile, IEventParser parser, ILogger logger)
{
_logFile = logFile;
_parser = parser;
@ -75,7 +73,9 @@ namespace IW4MAdmin.Application.IO
catch (Exception e)
{
_logger.LogError(e, "Could not properly parse event line {@eventLine}", eventLine);
_logger.WriteWarning("Could not properly parse event line");
_logger.WriteDebug(e.Message);
_logger.WriteDebug(eventLine);
}
}

View File

@ -6,8 +6,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.IO
{
@ -22,7 +20,7 @@ namespace IW4MAdmin.Application.IO
private readonly string _safeLogPath;
private string lastKey = "next";
public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger<GameLogReaderHttp> logger)
public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger logger)
{
_eventParser = parser;
_logServerApi = RestClient.For<IGameLogServer>(gameLogServerUris[0].ToString());
@ -42,7 +40,7 @@ namespace IW4MAdmin.Application.IO
if (!response.Success && string.IsNullOrEmpty(lastKey))
{
_logger.LogError("Could not get log server info of {logPath}", _safeLogPath);
_logger.WriteError($"Could not get log server info of {_safeLogPath}");
return events;
}
@ -64,7 +62,9 @@ namespace IW4MAdmin.Application.IO
catch (Exception e)
{
_logger.LogError(e, "Could not properly parse event line from http {eventLine}", eventLine);
_logger.WriteError("Could not properly parse event line from http");
_logger.WriteDebug(e.Message);
_logger.WriteDebug(eventLine);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,22 +6,15 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.Extensions.Logging;
using SharedLibraryCore.Configuration;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Localization
{
public static class Configure
public class Configure
{
public static ITranslationLookup Initialize(ILogger logger, IMasterApi apiInstance, ApplicationConfiguration applicationConfiguration)
public static ITranslationLookup Initialize(bool useLocalTranslation, IMasterApi apiInstance, string customLocale = null)
{
var useLocalTranslation = applicationConfiguration?.UseLocalTranslations ?? true;
var customLocale = applicationConfiguration?.EnableCustomLocale ?? false
? (applicationConfiguration.CustomLocale ?? "en-US")
: "en-US";
var currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale;
var localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json");
string currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale;
string[] localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json");
if (!useLocalTranslation)
{
@ -32,10 +25,9 @@ namespace IW4MAdmin.Application.Localization
return localization.LocalizationIndex;
}
catch (Exception ex)
catch (Exception)
{
// the online localization failed so will default to local files
logger.LogWarning(ex, "Could not download latest translations");
}
}
@ -63,20 +55,18 @@ namespace IW4MAdmin.Application.Localization
{
var localizationContents = File.ReadAllText(filePath, Encoding.UTF8);
var eachLocalizationFile = Newtonsoft.Json.JsonConvert.DeserializeObject<SharedLibraryCore.Localization.Layout>(localizationContents);
if (eachLocalizationFile == null)
{
continue;
}
foreach (var item in eachLocalizationFile.LocalizationIndex.Set)
{
if (!localizationDict.TryAdd(item.Key, item.Value))
{
logger.LogError("Could not add locale string {key} to localization", item.Key);
Program.ServerManager.GetLogger(0).WriteError($"Could not add locale string {item.Key} to localization");
}
}
}
string localizationFile = $"{Path.Join(Utilities.OperatingDirectory, "Localization")}{Path.DirectorySeparatorChar}IW4MAdmin.{currentLocale}-{currentLocale.ToUpper()}.json";
Utilities.CurrentLocalization = new SharedLibraryCore.Localization.Layout(localizationDict)
{
LocalizationName = currentLocale,

View File

@ -1,6 +1,7 @@
using IW4MAdmin.Application.API.Master;
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.Factories;
using IW4MAdmin.Application.Helpers;
using IW4MAdmin.Application.Meta;
using IW4MAdmin.Application.Migration;
using IW4MAdmin.Application.Misc;
@ -17,23 +18,12 @@ using SharedLibraryCore.QueryHelper;
using SharedLibraryCore.Repositories;
using SharedLibraryCore.Services;
using Stats.Dtos;
using StatsWeb;
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Helpers;
using Integrations.Source.Extensions;
using IW4MAdmin.Application.Extensions;
using IW4MAdmin.Application.Localization;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using IW4MAdmin.Plugins.Stats.Client.Abstractions;
using IW4MAdmin.Plugins.Stats.Client;
using Stats.Client.Abstractions;
using Stats.Client;
using Stats.Helpers;
namespace IW4MAdmin.Application
{
@ -75,10 +65,7 @@ namespace IW4MAdmin.Application
private static async void OnCancelKey(object sender, ConsoleCancelEventArgs e)
{
ServerManager?.Stop();
if (ApplicationTask != null)
{
await ApplicationTask;
}
await ApplicationTask;
}
/// <summary>
@ -87,40 +74,31 @@ namespace IW4MAdmin.Application
/// <returns></returns>
private static async Task LaunchAsync(string[] args)
{
restart:
restart:
ITranslationLookup translationLookup = null;
var logger = BuildDefaultLogger<Program>(new ApplicationConfiguration());
Utilities.DefaultLogger = logger;
IServiceCollection services = null;
logger.LogInformation("Begin IW4MAdmin startup. Version is {version} {@args}", Version, args);
try
{
// do any needed housekeeping file/folder migrations
ConfigurationMigration.MoveConfigFolder10518(null);
ConfigurationMigration.CheckDirectories();
ConfigurationMigration.RemoveObsoletePlugins20210322();
logger.LogDebug("Configuring services...");
services = ConfigureServices(args);
var services = ConfigureServices(args);
serviceProvider = services.BuildServiceProvider();
var versionChecker = serviceProvider.GetRequiredService<IMasterCommunication>();
ServerManager = (ApplicationManager) serviceProvider.GetRequiredService<IManager>();
ServerManager = (ApplicationManager)serviceProvider.GetRequiredService<IManager>();
translationLookup = serviceProvider.GetRequiredService<ITranslationLookup>();
ServerManager.Logger.WriteInfo(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_VERSION"].FormatExt(Version));
await versionChecker.CheckVersion();
await ServerManager.Init();
}
catch (Exception e)
{
string failMessage = translationLookup == null
? "Failed to initialize IW4MAdmin"
: translationLookup["MANAGER_INIT_FAIL"];
string exitMessage = translationLookup == null
? "Press enter to exit..."
: translationLookup["MANAGER_EXIT"];
string failMessage = translationLookup == null ? "Failed to initalize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"];
string exitMessage = translationLookup == null ? "Press enter to exit..." : translationLookup["MANAGER_EXIT"];
logger.LogCritical(e, "Failed to initialize IW4MAdmin");
Console.WriteLine(failMessage);
while (e.InnerException != null)
@ -132,8 +110,7 @@ namespace IW4MAdmin.Application
{
if (translationLookup != null)
{
Console.WriteLine(translationLookup[configException.Message]
.FormatExt(configException.ConfigurationFileName));
Console.WriteLine(translationLookup[configException.Message].FormatExt(configException.ConfigurationFileName));
}
foreach (string error in configException.Errors)
@ -154,16 +131,13 @@ namespace IW4MAdmin.Application
try
{
ApplicationTask = RunApplicationTasksAsync(logger, services);
ApplicationTask = RunApplicationTasksAsync();
await ApplicationTask;
}
catch (Exception e)
{
logger.LogCritical(e, "Failed to launch IW4MAdmin");
string failMessage = translationLookup == null
? "Failed to launch IW4MAdmin"
: translationLookup["MANAGER_INIT_FAIL"];
string failMessage = translationLookup == null ? "Failed to initalize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"];
Console.WriteLine($"{failMessage}: {e.GetExceptionInfo()}");
}
@ -179,33 +153,27 @@ namespace IW4MAdmin.Application
/// runs the core application tasks
/// </summary>
/// <returns></returns>
private static async Task RunApplicationTasksAsync(ILogger logger, IServiceCollection services)
private static async Task RunApplicationTasksAsync()
{
var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront
? WebfrontCore.Program.Init(ServerManager, serviceProvider, services, ServerManager.CancellationToken)
: Task.CompletedTask;
var collectionService = serviceProvider.GetRequiredService<IServerDataCollector>();
var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront ?
WebfrontCore.Program.Init(ServerManager, serviceProvider, ServerManager.CancellationToken) :
Task.CompletedTask;
// we want to run this one on a manual thread instead of letting the thread pool handle it,
// because we can't exit early from waiting on console input, and it prevents us from restarting
var inputThread = new Thread(async () => await ReadConsoleInput(logger));
var inputThread = new Thread(async () => await ReadConsoleInput());
inputThread.Start();
var tasks = new[]
{
ServerManager.Start(),
webfrontTask,
serviceProvider.GetRequiredService<IMasterCommunication>()
.RunUploadStatus(ServerManager.CancellationToken),
collectionService.BeginCollectionAsync(cancellationToken: ServerManager.CancellationToken)
serviceProvider.GetRequiredService<IMasterCommunication>().RunUploadStatus(ServerManager.CancellationToken)
};
logger.LogDebug("Starting webfront and input tasks");
await Task.WhenAll(tasks);
logger.LogInformation("Shutdown completed successfully");
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]);
ServerManager.Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]);
}
@ -213,11 +181,11 @@ namespace IW4MAdmin.Application
/// reads input from the console and executes entered commands on the default server
/// </summary>
/// <returns></returns>
private static async Task ReadConsoleInput(ILogger logger)
private static async Task ReadConsoleInput()
{
if (Console.IsInputRedirected)
{
logger.LogInformation("Disabling console input as it has been redirected");
ServerManager.Logger.WriteInfo("Disabling console input as it has been redirected");
return;
}
@ -250,133 +218,24 @@ namespace IW4MAdmin.Application
}
}
catch (OperationCanceledException)
{
}
{ }
}
private static IServiceCollection HandlePluginRegistration(ApplicationConfiguration appConfig,
IServiceCollection serviceCollection,
IMasterApi masterApi)
{
var defaultLogger = BuildDefaultLogger<Program>(appConfig);
var pluginServiceProvider = new ServiceCollection()
.AddBaseLogger(appConfig)
.AddSingleton(appConfig)
.AddSingleton(masterApi)
.AddSingleton<IRemoteAssemblyHandler, RemoteAssemblyHandler>()
.AddSingleton<IPluginImporter, PluginImporter>()
.BuildServiceProvider();
var pluginImporter = pluginServiceProvider.GetRequiredService<IPluginImporter>();
// we need to register the rest client with regular collection
serviceCollection.AddSingleton(masterApi);
// register the native commands
foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
.Concat(typeof(Program).Assembly.GetTypes().Where(type => type.Namespace == "IW4MAdmin.Application.Commands"))
.Where(_command => _command.BaseType == typeof(Command)))
{
defaultLogger.LogDebug("Registered native command type {name}", commandType.Name);
serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
}
// register the plugin implementations
var (plugins, commands, configurations) = pluginImporter.DiscoverAssemblyPluginImplementations();
foreach (var pluginType in plugins)
{
defaultLogger.LogDebug("Registered plugin type {name}", pluginType.FullName);
serviceCollection.AddSingleton(typeof(IPlugin), pluginType);
}
// register the plugin commands
foreach (var commandType in commands)
{
defaultLogger.LogDebug("Registered plugin command type {name}", commandType.FullName);
serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
}
foreach (var configurationType in configurations)
{
defaultLogger.LogDebug("Registered plugin config type {name}", configurationType.Name);
var configInstance = (IBaseConfiguration) Activator.CreateInstance(configurationType);
var handlerType = typeof(BaseConfigurationHandler<>).MakeGenericType(configurationType);
var handlerInstance = Activator.CreateInstance(handlerType, new[] {configInstance.Name()});
var genericInterfaceType = typeof(IConfigurationHandler<>).MakeGenericType(configurationType);
serviceCollection.AddSingleton(genericInterfaceType, handlerInstance);
}
// register any script plugins
foreach (var scriptPlugin in pluginImporter.DiscoverScriptPlugins())
{
serviceCollection.AddSingleton(scriptPlugin);
}
// register any eventable types
foreach (var assemblyType in typeof(Program).Assembly.GetTypes()
.Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))
.Union(plugins.SelectMany(_asm => _asm.Assembly.GetTypes())
.Distinct()
.Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))))
{
var instance = Activator.CreateInstance(assemblyType) as IRegisterEvent;
serviceCollection.AddSingleton(instance);
}
return serviceCollection;
}
/// <summary>
/// Configures the dependency injection services
/// </summary>
private static IServiceCollection ConfigureServices(string[] args)
{
// setup the static resources (config/master api/translations)
var defaultLogger = new Logger("IW4MAdmin-Manager");
var pluginImporter = new PluginImporter(defaultLogger);
var serviceCollection = new ServiceCollection();
var appConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
var defaultConfigHandler = new BaseConfigurationHandler<DefaultSettings>("DefaultSettings");
var defaultConfig = defaultConfigHandler.Configuration();
var appConfig = appConfigHandler.Configuration();
var masterUri = Utilities.IsDevelopment
? new Uri("http://127.0.0.1:8080")
: appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
var masterRestClient = RestClient.For<IMasterApi>(masterUri);
var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig);
if (appConfig == null)
{
appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate();
appConfigHandler.Set(appConfig);
appConfigHandler.Save();
}
// register override level names
foreach (var (key, value) in appConfig.OverridePermissionLevelNames)
{
if (!Utilities.PermissionLevelOverrides.ContainsKey(key))
{
Utilities.PermissionLevelOverrides.Add(key, value);
}
}
// build the dependency list
HandlePluginRegistration(appConfig, serviceCollection, masterRestClient);
serviceCollection
.AddBaseLogger(appConfig)
.AddSingleton(defaultConfig)
.AddSingleton<IServiceCollection>(_serviceProvider => serviceCollection)
.AddSingleton<IConfigurationHandler<DefaultSettings>, BaseConfigurationHandler<DefaultSettings>>()
.AddSingleton((IConfigurationHandler<ApplicationConfiguration>) appConfigHandler)
.AddSingleton(
new BaseConfigurationHandler<CommandConfiguration>("CommandConfiguration") as
IConfigurationHandler<CommandConfiguration>)
.AddSingleton(appConfig)
.AddSingleton(_serviceProvider =>
_serviceProvider.GetRequiredService<IConfigurationHandler<CommandConfiguration>>()
.Configuration() ?? new CommandConfiguration())
serviceCollection.AddSingleton<IServiceCollection>(_serviceProvider => serviceCollection)
.AddSingleton(new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings") as IConfigurationHandler<ApplicationConfiguration>)
.AddSingleton(new BaseConfigurationHandler<CommandConfiguration>("CommandConfiguration") as IConfigurationHandler<CommandConfiguration>)
.AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService<IConfigurationHandler<ApplicationConfiguration>>().Configuration() ?? new ApplicationConfiguration())
.AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService<IConfigurationHandler<CommandConfiguration>>().Configuration() ?? new CommandConfiguration())
.AddSingleton<ILogger>(_serviceProvider => defaultLogger)
.AddSingleton<IPluginImporter, PluginImporter>()
.AddSingleton<IMiddlewareActionHandler, MiddlewareActionHandler>()
.AddSingleton<IRConConnectionFactory, RConConnectionFactory>()
@ -389,36 +248,26 @@ namespace IW4MAdmin.Application
.AddSingleton<IAuditInformationRepository, AuditInformationRepository>()
.AddSingleton<IEntityService<EFClient>, ClientService>()
.AddSingleton<IMetaService, MetaService>()
.AddSingleton<ClientService>()
.AddSingleton<PenaltyService>()
.AddSingleton<ChangeHistoryService>()
.AddSingleton<IMetaRegistration, MetaRegistration>()
.AddSingleton<IScriptPluginServiceResolver, ScriptPluginServiceResolver>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, ReceivedPenaltyResponse>,
ReceivedPenaltyResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, AdministeredPenaltyResponse>,
AdministeredPenaltyResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, UpdatedAliasResponse>,
UpdatedAliasResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, ReceivedPenaltyResponse>, ReceivedPenaltyResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, AdministeredPenaltyResponse>, AdministeredPenaltyResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, UpdatedAliasResponse>, UpdatedAliasResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ChatSearchQuery, MessageResponse>, ChatResourceQueryHelper>()
.AddSingleton<IResourceQueryHelper<ClientPaginationRequest, ConnectionHistoryResponse>, ConnectionsResourceQueryHelper>()
.AddTransient<IParserPatternMatcher, ParserPatternMatcher>()
.AddSingleton<IRemoteAssemblyHandler, RemoteAssemblyHandler>()
.AddSingleton<IMasterCommunication, MasterCommunication>()
.AddSingleton(_serviceProvider =>
{
var config = _serviceProvider.GetRequiredService<IConfigurationHandler<ApplicationConfiguration>>().Configuration();
return Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false,
apiInstance: _serviceProvider.GetRequiredService<IMasterApi>(),
customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US");
})
.AddSingleton<IManager, ApplicationManager>()
.AddSingleton<SharedLibraryCore.Interfaces.ILogger, Logger>()
.AddSingleton<IClientNoticeMessageFormatter, ClientNoticeMessageFormatter>()
.AddSingleton<IClientStatisticCalculator, HitCalculator>()
.AddSingleton<IServerDistributionCalculator, ServerDistributionCalculator>()
.AddSingleton<IWeaponNameParser, WeaponNameParser>()
.AddSingleton<IHitInfoBuilder, HitInfoBuilder>()
.AddSingleton(typeof(ILookupCache<>), typeof(LookupCache<>))
.AddSingleton(typeof(IDataValueCache<,>), typeof(DataValueCache<,>))
.AddSingleton<IServerDataViewer, ServerDataViewer>()
.AddSingleton<IServerDataCollector, ServerDataCollector>()
.AddSingleton<IEventPublisher, EventPublisher>()
.AddSingleton(translationLookup)
.AddDatabaseContextOptions(appConfig);
.AddSingleton(_serviceProvider => RestClient
.For<IMasterApi>(Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : _serviceProvider
.GetRequiredService<IConfigurationHandler<ApplicationConfiguration>>().Configuration()?.MasterUrl ??
new ApplicationConfiguration().MasterUrl))
.AddSingleton<IMasterCommunication, MasterCommunication>();
if (args.Contains("serialevents"))
{
@ -429,18 +278,48 @@ namespace IW4MAdmin.Application
serviceCollection.AddSingleton<IEventHandler, GameEventHandler>();
}
serviceCollection.AddSource();
// register the native commands
foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
.Where(_command => _command.BaseType == typeof(Command)))
{
defaultLogger.WriteInfo($"Registered native command type {commandType.Name}");
serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
}
// register the plugin implementations
var pluginImplementations = pluginImporter.DiscoverAssemblyPluginImplementations();
foreach (var pluginType in pluginImplementations.Item1)
{
defaultLogger.WriteInfo($"Registered plugin type {pluginType.FullName}");
serviceCollection.AddSingleton(typeof(IPlugin), pluginType);
}
// register the plugin commands
foreach (var commandType in pluginImplementations.Item2)
{
defaultLogger.WriteInfo($"Registered plugin command type {commandType.FullName}");
serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
}
// register any script plugins
foreach (var scriptPlugin in pluginImporter.DiscoverScriptPlugins())
{
serviceCollection.AddSingleton(scriptPlugin);
}
// register any eventable types
foreach (var assemblyType in typeof(Program).Assembly.GetTypes()
.Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))
.Union(pluginImplementations
.Item1.SelectMany(_asm => _asm.Assembly.GetTypes())
.Distinct()
.Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))))
{
var instance = Activator.CreateInstance(assemblyType) as IRegisterEvent;
serviceCollection.AddSingleton(instance);
}
return serviceCollection;
}
private static ILogger BuildDefaultLogger<T>(ApplicationConfiguration appConfig)
{
var collection = new ServiceCollection()
.AddBaseLogger(appConfig)
.BuildServiceProvider();
return collection.GetRequiredService<ILogger<T>>();
}
}
}

View File

@ -1,14 +1,11 @@
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Meta
{
@ -21,7 +18,7 @@ namespace IW4MAdmin.Application.Meta
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
public AdministeredPenaltyResourceQueryHelper(ILogger<AdministeredPenaltyResourceQueryHelper> logger, IDatabaseContextFactory contextFactory)
public AdministeredPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory)
{
_contextFactory = contextFactory;
_logger = logger;
@ -29,7 +26,7 @@ namespace IW4MAdmin.Application.Meta
public async Task<ResourceQueryHelperResult<AdministeredPenaltyResponse>> QueryResource(ClientPaginationRequest query)
{
await using var ctx = _contextFactory.CreateContext(enableTracking: false);
using var ctx = _contextFactory.CreateContext(enableTracking: false);
var iqPenalties = ctx.Penalties.AsNoTracking()
.Where(_penalty => query.ClientId == _penalty.PunisherId)

View File

@ -1,60 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Meta
{
public class
ConnectionsResourceQueryHelper : IResourceQueryHelper<ClientPaginationRequest, ConnectionHistoryResponse>
{
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
public ConnectionsResourceQueryHelper(ILogger<ConnectionsResourceQueryHelper> logger,
IDatabaseContextFactory contextFactory)
{
_contextFactory = contextFactory;
_logger = logger;
}
public async Task<ResourceQueryHelperResult<ConnectionHistoryResponse>> QueryResource(
ClientPaginationRequest query)
{
_logger.LogDebug("{Class} {@Request}", nameof(ConnectionsResourceQueryHelper), query);
await using var context = _contextFactory.CreateContext(enableTracking: false);
var iqConnections = context.ConnectionHistory.AsNoTracking()
.Where(history => query.ClientId == history.ClientId)
.Where(history => history.CreatedDateTime < query.Before)
.OrderByDescending(history => history.CreatedDateTime);
var connections = await iqConnections.Select(history => new ConnectionHistoryResponse
{
MetaId = history.ClientConnectionId,
ClientId = history.ClientId,
Type = MetaType.ConnectionHistory,
ShouldDisplay = true,
When = history.CreatedDateTime,
ServerName = history.Server.HostName,
ConnectionType = history.ConnectionType
})
.ToListAsync();
_logger.LogDebug("{Class} retrieved {Number} items", nameof(ConnectionsResourceQueryHelper),
connections.Count);
return new ResourceQueryHelperResult<ConnectionHistoryResponse>
{
Results = connections
};
}
}
}

View File

@ -6,8 +6,6 @@ using SharedLibraryCore.QueryHelper;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Meta
{
@ -20,14 +18,11 @@ namespace IW4MAdmin.Application.Meta
private readonly IResourceQueryHelper<ClientPaginationRequest, ReceivedPenaltyResponse> _receivedPenaltyHelper;
private readonly IResourceQueryHelper<ClientPaginationRequest, AdministeredPenaltyResponse> _administeredPenaltyHelper;
private readonly IResourceQueryHelper<ClientPaginationRequest, UpdatedAliasResponse> _updatedAliasHelper;
private readonly IResourceQueryHelper<ClientPaginationRequest, ConnectionHistoryResponse>
_connectionHistoryHelper;
public MetaRegistration(ILogger<MetaRegistration> logger, IMetaService metaService, ITranslationLookup transLookup, IEntityService<EFClient> clientEntityService,
public MetaRegistration(ILogger logger, IMetaService metaService, ITranslationLookup transLookup, IEntityService<EFClient> clientEntityService,
IResourceQueryHelper<ClientPaginationRequest, ReceivedPenaltyResponse> receivedPenaltyHelper,
IResourceQueryHelper<ClientPaginationRequest, AdministeredPenaltyResponse> administeredPenaltyHelper,
IResourceQueryHelper<ClientPaginationRequest, UpdatedAliasResponse> updatedAliasHelper,
IResourceQueryHelper<ClientPaginationRequest, ConnectionHistoryResponse> connectionHistoryHelper)
IResourceQueryHelper<ClientPaginationRequest, UpdatedAliasResponse> updatedAliasHelper)
{
_logger = logger;
_transLookup = transLookup;
@ -36,7 +31,6 @@ namespace IW4MAdmin.Application.Meta
_receivedPenaltyHelper = receivedPenaltyHelper;
_administeredPenaltyHelper = administeredPenaltyHelper;
_updatedAliasHelper = updatedAliasHelper;
_connectionHistoryHelper = connectionHistoryHelper;
}
public void Register()
@ -45,7 +39,6 @@ namespace IW4MAdmin.Application.Meta
_metaService.AddRuntimeMeta<ClientPaginationRequest, ReceivedPenaltyResponse>(MetaType.ReceivedPenalty, GetReceivedPenaltiesMeta);
_metaService.AddRuntimeMeta<ClientPaginationRequest, AdministeredPenaltyResponse>(MetaType.Penalized, GetAdministeredPenaltiesMeta);
_metaService.AddRuntimeMeta<ClientPaginationRequest, UpdatedAliasResponse>(MetaType.AliasUpdate, GetUpdatedAliasMeta);
_metaService.AddRuntimeMeta<ClientPaginationRequest, ConnectionHistoryResponse>(MetaType.ConnectionHistory, GetConnectionHistoryMeta);
}
private async Task<IEnumerable<InformationResponse>> GetProfileMeta(ClientPaginationRequest request)
@ -89,7 +82,7 @@ namespace IW4MAdmin.Application.Meta
if (client == null)
{
_logger.LogWarning("No client found with id {clientId} when generating profile meta", request.ClientId);
_logger.WriteWarning($"No client found with id {request.ClientId} when generating profile meta");
return metaList;
}
@ -168,11 +161,5 @@ namespace IW4MAdmin.Application.Meta
var aliases = await _updatedAliasHelper.QueryResource(request);
return aliases.Results;
}
private async Task<IEnumerable<ConnectionHistoryResponse>> GetConnectionHistoryMeta(ClientPaginationRequest request)
{
var connections = await _connectionHistoryHelper.QueryResource(request);
return connections.Results;
}
}
}

View File

@ -1,17 +1,13 @@
using System.Collections.Generic;
using System;
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Meta
{
@ -23,50 +19,29 @@ namespace IW4MAdmin.Application.Meta
{
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
private readonly ApplicationConfiguration _appConfig;
public ReceivedPenaltyResourceQueryHelper(ILogger<ReceivedPenaltyResourceQueryHelper> logger,
IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig)
public ReceivedPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory)
{
_contextFactory = contextFactory;
_logger = logger;
_appConfig = appConfig;
}
public async Task<ResourceQueryHelperResult<ReceivedPenaltyResponse>> QueryResource(ClientPaginationRequest query)
{
var linkedPenaltyType = Utilities.LinkedPenaltyTypes();
await using var ctx = _contextFactory.CreateContext(enableTracking: false);
using var ctx = _contextFactory.CreateContext(enableTracking: false);
var linkId = await ctx.Clients.AsNoTracking()
.Where(_client => _client.ClientId == query.ClientId)
.Select(_client => new {_client.AliasLinkId, _client.CurrentAliasId })
.Select(_client => _client.AliasLinkId)
.FirstOrDefaultAsync();
var iqPenalties = ctx.Penalties.AsNoTracking()
.Where(_penalty => _penalty.OffenderId == query.ClientId ||
linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId.AliasLinkId);
var iqIpLinkedPenalties = new List<EFPenalty>().AsQueryable();
if (!_appConfig.EnableImplicitAccountLinking)
{
var usedIps = await ctx.Aliases.AsNoTracking()
.Where(alias => (alias.LinkId == linkId.AliasLinkId || alias.AliasId == linkId.CurrentAliasId) && alias.IPAddress != null)
.Select(alias => alias.IPAddress).ToListAsync();
var aliasedIds = await ctx.Aliases.AsNoTracking().Where(alias => usedIps.Contains(alias.IPAddress))
.Select(alias => alias.LinkId)
.ToListAsync();
iqIpLinkedPenalties = ctx.Penalties.AsNoTracking()
.Where(penalty =>
linkedPenaltyType.Contains(penalty.Type) && aliasedIds.Contains(penalty.LinkId));
}
var penalties = await iqPenalties.Union(iqIpLinkedPenalties)
.Where(_penalty => _penalty.OffenderId == query.ClientId || (linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId))
.Where(_penalty => _penalty.When < query.Before)
.OrderByDescending(_penalty => _penalty.When)
.OrderByDescending(_penalty => _penalty.When);
var penalties = await iqPenalties
.Take(query.Count)
.Select(_penalty => new ReceivedPenaltyResponse()
{

View File

@ -6,9 +6,6 @@ using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Meta
{
@ -21,7 +18,7 @@ namespace IW4MAdmin.Application.Meta
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
public UpdatedAliasResourceQueryHelper(ILogger<UpdatedAliasResourceQueryHelper> logger, IDatabaseContextFactory contextFactory)
public UpdatedAliasResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory)
{
_logger = logger;
_contextFactory = contextFactory;
@ -29,7 +26,7 @@ namespace IW4MAdmin.Application.Meta
public async Task<ResourceQueryHelperResult<UpdatedAliasResponse>> QueryResource(ClientPaginationRequest query)
{
await using var ctx = _contextFactory.CreateContext(enableTracking: false);
using var ctx = _contextFactory.CreateContext(enableTracking: false);
int linkId = ctx.Clients.First(_client => _client.ClientId == query.ClientId).AliasLinkId;
var iqAliasUpdates = ctx.Aliases

View File

@ -1,8 +1,11 @@
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using System.Text;
using System.Text.RegularExpressions;
namespace IW4MAdmin.Application.Migration
{
@ -53,6 +56,7 @@ namespace IW4MAdmin.Application.Migration
if (!Directory.Exists(configDirectory))
{
log?.WriteDebug($"Creating directory for configs {configDirectory}");
Directory.CreateDirectory(configDirectory);
}
@ -62,6 +66,7 @@ namespace IW4MAdmin.Application.Migration
foreach (var configFile in configurationFiles)
{
log?.WriteDebug($"Moving config file {configFile}");
string destinationPath = Path.Join("Configuration", configFile);
if (!File.Exists(destinationPath))
{
@ -72,6 +77,7 @@ namespace IW4MAdmin.Application.Migration
if (!File.Exists(Path.Join("Database", "Database.db")) &&
File.Exists("Database.db"))
{
log?.WriteDebug("Moving database file");
File.Move("Database.db", Path.Join("Database", "Database.db"));
}
}
@ -85,20 +91,5 @@ namespace IW4MAdmin.Application.Migration
config.ManualLogPath = null;
}
}
public static void RemoveObsoletePlugins20210322()
{
var files = new[] {"StatsWeb.dll", "StatsWeb.Views.dll"};
foreach (var file in files)
{
var path = Path.Join(Utilities.OperatingDirectory, "Plugins", file);
if (File.Exists(path))
{
File.Delete(path);
}
}
}
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models.Client.Stats;
namespace IW4MAdmin.Application.Migration
{
public static class DatabaseHousekeeping
{
private static readonly DateTime CutoffDate = DateTime.UtcNow.AddMonths(-6);
public static async Task RemoveOldRatings(IDatabaseContextFactory contextFactory, CancellationToken token)
{
await using var context = contextFactory.CreateContext();
var dbSet = context.Set<EFRating>();
var itemsToDelete = dbSet.Where(rating => rating.When <= CutoffDate);
dbSet.RemoveRange(itemsToDelete);
await context.SaveChangesAsync(token);
}
}
}

View File

@ -22,11 +22,6 @@ namespace IW4MAdmin.Application.Misc
Build();
}
public BaseConfigurationHandler() : this(typeof(T).Name)
{
}
public string FileName { get; }
public void Build()

View File

@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Data.Models;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.Misc
{
/// <summary>
/// implementation of IClientNoticeMessageFormatter
/// </summary>
public class ClientNoticeMessageFormatter : IClientNoticeMessageFormatter
{
private readonly ITranslationLookup _transLookup;
private readonly ApplicationConfiguration _appConfig;
public ClientNoticeMessageFormatter(ITranslationLookup transLookup, ApplicationConfiguration appConfig)
{
_transLookup = transLookup;
_appConfig = appConfig;
}
public string BuildFormattedMessage(IRConParserConfiguration config, EFPenalty currentPenalty, EFPenalty originalPenalty = null)
{
var isNewLineSeparator = config.NoticeLineSeparator == Environment.NewLine;
var penalty = originalPenalty ?? currentPenalty;
var builder = new StringBuilder();
// build the top level header
var header = _transLookup[$"SERVER_{penalty.Type.ToString().ToUpper()}_TEXT"];
builder.Append(header);
builder.Append(config.NoticeLineSeparator);
// build the reason
var reason = _transLookup["GAME_MESSAGE_PENALTY_REASON"].FormatExt(penalty.Offense);
if (isNewLineSeparator)
{
foreach (var splitReason in SplitOverMaxLength(reason, config.NoticeMaxCharactersPerLine))
{
builder.Append(splitReason);
builder.Append(config.NoticeLineSeparator);
}
}
else
{
builder.Append(reason);
builder.Append(config.NoticeLineSeparator);
}
if (penalty.Type == EFPenalty.PenaltyType.TempBan)
{
// build the time remaining if temporary
var timeRemainingValue = penalty.Expires.HasValue
? (penalty.Expires - DateTime.UtcNow).Value.HumanizeForCurrentCulture()
: "--";
var timeRemaining = _transLookup["GAME_MESSAGE_PENALTY_TIME_REMAINING"].FormatExt(timeRemainingValue);
if (isNewLineSeparator)
{
foreach (var splitReason in SplitOverMaxLength(timeRemaining, config.NoticeMaxCharactersPerLine))
{
builder.Append(splitReason);
builder.Append(config.NoticeLineSeparator);
}
}
else
{
builder.Append(timeRemaining);
}
}
if (penalty.Type == EFPenalty.PenaltyType.Ban)
{
// provide a place to appeal the ban (should always be specified but including a placeholder just incase)
builder.Append(_transLookup["GAME_MESSAGE_PENALTY_APPEAL"].FormatExt(_appConfig.ContactUri ?? "--"));
}
// final format looks something like:
/*
* You are permanently banned
* Reason - toxic behavior
* Visit example.com to appeal
*/
return builder.ToString();
}
private static IEnumerable<string> SplitOverMaxLength(string source, int maxCharactersPerLine)
{
if (source.Length <= maxCharactersPerLine)
{
return new[] {source};
}
var segments = new List<string>();
var currentLocation = 0;
while (currentLocation < source.Length)
{
var nextLocation = currentLocation + maxCharactersPerLine;
// there's probably a more efficient way to do this but this is readable
segments.Add(string.Concat(
source
.Skip(currentLocation)
.Take(Math.Min(maxCharactersPerLine, source.Length - currentLocation))));
currentLocation = nextLocation;
}
if (currentLocation < source.Length)
{
segments.Add(source.Substring(currentLocation, source.Length - currentLocation));
}
return segments;
}
}
}

View File

@ -0,0 +1,63 @@
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace IW4MAdmin.Application.Misc
{
internal class EventPerformance
{
public long ExecutionTime { get; set; }
public GameEvent Event { get; set; }
public string EventInfo => $"{Event.Type}, {Event.FailReason}, {Event.IsBlocking}, {Event.Data}, {Event.Message}, {Event.Extra}";
}
public class DuplicateKeyComparer<TKey> : IComparer<TKey> where TKey : IComparable
{
public int Compare(TKey x, TKey y)
{
int result = x.CompareTo(y);
if (result == 0)
return 1;
else
return result;
}
}
internal class EventProfiler
{
public double AverageEventTime { get; private set; }
public double MaxEventTime => Events.Values.Last().ExecutionTime;
public double MinEventTime => Events.Values[0].ExecutionTime;
public int TotalEventCount => Events.Count;
public SortedList<long, EventPerformance> Events { get; private set; } = new SortedList<long, EventPerformance>(new DuplicateKeyComparer<long>());
private readonly ILogger _logger;
public EventProfiler(ILogger logger)
{
_logger = logger;
}
public void Profile(DateTime start, DateTime end, GameEvent gameEvent)
{
_logger.WriteDebug($"Starting profile of event {gameEvent.Id}");
long executionTime = (long)Math.Round((end - start).TotalMilliseconds);
var perf = new EventPerformance()
{
Event = gameEvent,
ExecutionTime = executionTime
};
lock (Events)
{
Events.Add(executionTime, perf);
}
AverageEventTime = (AverageEventTime * (TotalEventCount - 1) + executionTime) / TotalEventCount;
_logger.WriteDebug($"Finished profile of event {gameEvent.Id}");
}
}
}

View File

@ -1,44 +0,0 @@
using System;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
public class EventPublisher : IEventPublisher
{
public event EventHandler<GameEvent> OnClientDisconnect;
public event EventHandler<GameEvent> OnClientConnect;
private readonly ILogger _logger;
public EventPublisher(ILogger<EventPublisher> logger)
{
_logger = logger;
}
public void Publish(GameEvent gameEvent)
{
_logger.LogDebug("Handling publishing event of type {EventType}", gameEvent.Type);
try
{
if (gameEvent.Type == GameEvent.EventType.Connect)
{
OnClientConnect?.Invoke(this, gameEvent);
}
if (gameEvent.Type == GameEvent.EventType.Disconnect)
{
OnClientDisconnect?.Invoke(this, gameEvent);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not publish event of type {EventType}", gameEvent.Type);
}
}
}
}

View File

@ -19,12 +19,6 @@ namespace IW4MAdmin.Application.Misc
/// </summary>
public string BasePathDirectory { get; set; } = "";
/// <summary>
/// directory for local storage
/// <remarks>fs_homepath</remarks>
/// </summary>
public string HomePathDirectory { get; set; } = "";
/// <summary>
/// overide game directory
/// <remarks>plugin driven</remarks>
@ -47,11 +41,5 @@ namespace IW4MAdmin.Application.Misc
/// indicates if running on windows
/// </summary>
public bool IsWindows { get; set; } = true;
/// <summary>
/// indicates that the game does not log to the mods folder (when mod is loaded),
/// but rather always to the fs_basegame directory
/// </summary>
public bool IsOneLog { get; set; }
}
}

View File

@ -1,47 +1,132 @@
using System;
using Microsoft.Extensions.Logging;
using ILogger = SharedLibraryCore.Interfaces.ILogger;
using IW4MAdmin.Application.IO;
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
namespace IW4MAdmin.Application
{
[Obsolete]
public class Logger : ILogger
{
private readonly Microsoft.Extensions.Logging.ILogger _logger;
public Logger(ILogger<Logger> logger)
enum LogType
{
_logger = logger;
Verbose,
Info,
Debug,
Warning,
Error,
Assert
}
readonly string FileName;
readonly ReaderWriterLockSlim WritingLock;
static readonly short MAX_LOG_FILES = 10;
public Logger(string fn)
{
FileName = Path.Join(Utilities.OperatingDirectory, "Log", $"{fn}.log");
WritingLock = new ReaderWriterLockSlim();
RotateLogs();
}
~Logger()
{
WritingLock.Dispose();
}
/// <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)
{
WritingLock.EnterWriteLock();
string stringType = type.ToString();
msg = msg.StripColors();
try
{
stringType = Utilities.CurrentLocalization.LocalizationIndex[$"GLOBAL_{type.ToString().ToUpper()}"];
}
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(msg);
#else
if (type == LogType.Error || type == LogType.Verbose)
{
Console.WriteLine(LogLine);
}
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());
}
WritingLock.ExitWriteLock();
}
public void WriteVerbose(string msg)
{
_logger.LogInformation(msg);
Write(msg, LogType.Verbose);
}
public void WriteDebug(string msg)
{
_logger.LogDebug(msg);
Write(msg, LogType.Debug);
}
public void WriteError(string msg)
{
_logger.LogError(msg);
Write(msg, LogType.Error);
}
public void WriteInfo(string msg)
{
WriteVerbose(msg);
Write(msg, LogType.Info);
}
public void WriteWarning(string msg)
{
_logger.LogWarning(msg);
Write(msg, LogType.Warning);
}
public void WriteAssert(bool condition, string msg)
{
throw new NotImplementedException();
if (!condition)
Write(msg, LogType.Assert);
}
}
}

View File

@ -8,8 +8,6 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
@ -26,9 +24,10 @@ namespace IW4MAdmin.Application.Misc
private readonly ApplicationConfiguration _appConfig;
private readonly BuildNumber _fallbackVersion = BuildNumber.Parse("99.99.99.99");
private readonly int _apiVersion = 1;
private bool firstHeartBeat = true;
public MasterCommunication(ILogger<MasterCommunication> logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager)
public MasterCommunication(ILogger logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager)
{
_logger = logger;
_transLookup = translationLookup;
@ -56,7 +55,13 @@ namespace IW4MAdmin.Application.Misc
catch (Exception e)
{
_logger.LogWarning(e, "Unable to retrieve IW4MAdmin version information");
_logger.WriteWarning(_transLookup["MANAGER_VERSION_FAIL"]);
while (e.InnerException != null)
{
e = e.InnerException;
}
_logger.WriteDebug(e.Message);
}
if (version.CurrentVersionStable == _fallbackVersion)
@ -105,12 +110,12 @@ namespace IW4MAdmin.Application.Misc
catch (System.Net.Http.HttpRequestException e)
{
_logger.LogWarning(e, "Could not send heartbeat");
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
catch (AggregateException e)
{
_logger.LogWarning(e, "Could not send heartbeat");
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
var exceptions = e.InnerExceptions.Where(ex => ex.GetType() == typeof(ApiException));
foreach (var ex in exceptions)
@ -124,7 +129,7 @@ namespace IW4MAdmin.Application.Misc
catch (ApiException e)
{
_logger.LogWarning(e, "Could not send heartbeat");
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
if (e.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
connected = false;
@ -133,7 +138,7 @@ namespace IW4MAdmin.Application.Misc
catch (Exception e)
{
_logger.LogWarning(e, "Could not send heartbeat");
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
@ -197,7 +202,7 @@ namespace IW4MAdmin.Application.Misc
if (response.ResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.LogWarning("Non success response code from master is {statusCode}, message is {message}", response.ResponseMessage.StatusCode, response.StringContent);
_logger.WriteWarning($"Response code from master is {response.ResponseMessage.StatusCode}, message is {response.StringContent}");
}
}
}

View File

@ -7,10 +7,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using Data.Models;
namespace IW4MAdmin.Application.Misc
{
@ -24,14 +20,14 @@ namespace IW4MAdmin.Application.Misc
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
public MetaService(ILogger<MetaService> logger, IDatabaseContextFactory contextFactory)
public MetaService(ILogger logger, IDatabaseContextFactory contextFactory)
{
_logger = logger;
_metaActions = new Dictionary<MetaType, List<dynamic>>();
_contextFactory = contextFactory;
}
public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client, EFMeta linkedMeta = null)
public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client)
{
// this seems to happen if the client disconnects before they've had time to authenticate and be added
if (client.ClientId < 1)
@ -39,7 +35,7 @@ namespace IW4MAdmin.Application.Misc
return;
}
await using var ctx = _contextFactory.CreateContext();
using var ctx = _contextFactory.CreateContext();
var existingMeta = await ctx.EFMeta
.Where(_meta => _meta.Key == metaKey)
@ -50,7 +46,6 @@ namespace IW4MAdmin.Application.Misc
{
existingMeta.Value = metaValue;
existingMeta.Updated = DateTime.UtcNow;
existingMeta.LinkedMetaId = linkedMeta?.MetaId;
}
else
@ -60,101 +55,16 @@ namespace IW4MAdmin.Application.Misc
ClientId = client.ClientId,
Created = DateTime.UtcNow,
Key = metaKey,
Value = metaValue,
LinkedMetaId = linkedMeta?.MetaId
Value = metaValue
});
}
await ctx.SaveChangesAsync();
}
public async Task AddPersistentMeta(string metaKey, string metaValue)
{
await using var ctx = _contextFactory.CreateContext();
var existingMeta = await ctx.EFMeta
.Where(meta => meta.Key == metaKey)
.Where(meta => meta.ClientId == null)
.ToListAsync();
var matchValues = existingMeta
.Where(meta => meta.Value == metaValue)
.ToArray();
if (matchValues.Any())
{
foreach (var meta in matchValues)
{
_logger.LogDebug("Updating existing meta with key {key} and id {id}", meta.Key, meta.MetaId);
meta.Value = metaValue;
meta.Updated = DateTime.UtcNow;
}
await ctx.SaveChangesAsync();
}
else
{
_logger.LogDebug("Adding new meta with key {key}", metaKey);
ctx.EFMeta.Add(new EFMeta()
{
Created = DateTime.UtcNow,
Key = metaKey,
Value = metaValue
});
await ctx.SaveChangesAsync();
}
}
public async Task RemovePersistentMeta(string metaKey, EFClient client)
{
await using var context = _contextFactory.CreateContext();
var existingMeta = await context.EFMeta
.FirstOrDefaultAsync(meta => meta.Key == metaKey && meta.ClientId == client.ClientId);
if (existingMeta == null)
{
_logger.LogDebug("No meta with key {key} found for client id {id}", metaKey, client.ClientId);
return;
}
_logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, existingMeta.MetaId);
context.EFMeta.Remove(existingMeta);
await context.SaveChangesAsync();
}
public async Task RemovePersistentMeta(string metaKey, string metaValue = null)
{
await using var context = _contextFactory.CreateContext(enableTracking: false);
var existingMeta = await context.EFMeta
.Where(meta => meta.Key == metaKey)
.Where(meta => meta.ClientId == null)
.ToListAsync();
if (metaValue == null)
{
_logger.LogDebug("Removing all meta for key {key} with ids [{ids}] ", metaKey, string.Join(", ", existingMeta.Select(meta => meta.MetaId)));
existingMeta.ForEach(meta => context.Remove(existingMeta));
await context.SaveChangesAsync();
return;
}
var foundMeta = existingMeta.FirstOrDefault(meta => meta.Value == metaValue);
if (foundMeta != null)
{
_logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, foundMeta.MetaId);
context.Remove(foundMeta);
await context.SaveChangesAsync();
}
}
public async Task<EFMeta> GetPersistentMeta(string metaKey, EFClient client)
{
await using var ctx = _contextFactory.CreateContext(enableTracking: false);
using var ctx = _contextFactory.CreateContext(enableTracking: false);
return await ctx.EFMeta
.Where(_meta => _meta.Key == metaKey)
@ -164,34 +74,11 @@ namespace IW4MAdmin.Application.Misc
MetaId = _meta.MetaId,
Key = _meta.Key,
ClientId = _meta.ClientId,
Value = _meta.Value,
LinkedMetaId = _meta.LinkedMetaId,
LinkedMeta = _meta.LinkedMetaId != null ? new EFMeta()
{
MetaId = _meta.LinkedMeta.MetaId,
Key = _meta.LinkedMeta.Key,
Value = _meta.LinkedMeta.Value
} : null
Value = _meta.Value
})
.FirstOrDefaultAsync();
}
public async Task<IEnumerable<EFMeta>> GetPersistentMeta(string metaKey)
{
await using var context = _contextFactory.CreateContext(enableTracking: false);
return await context.EFMeta
.Where(meta => meta.Key == metaKey)
.Where(meta => meta.ClientId == null)
.Select(meta => new EFMeta
{
MetaId = meta.MetaId,
Key = meta.Key,
ClientId = meta.ClientId,
Value = meta.Value,
})
.ToListAsync();
}
public void AddRuntimeMeta<T, V>(MetaType metaKey, Func<T, Task<IEnumerable<V>>> metaAction) where T : PaginationRequest where V : IClientMeta
{
if (!_metaActions.ContainsKey(metaKey))

View File

@ -1,9 +1,8 @@
using SharedLibraryCore.Interfaces;
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
@ -12,7 +11,7 @@ namespace IW4MAdmin.Application.Misc
private readonly IDictionary<string, IList<object>> _actions;
private readonly ILogger _logger;
public MiddlewareActionHandler(ILogger<MiddlewareActionHandler> logger)
public MiddlewareActionHandler(ILogger logger)
{
_actions = new Dictionary<string, IList<object>>();
_logger = logger;
@ -39,7 +38,8 @@ namespace IW4MAdmin.Application.Misc
}
catch (Exception e)
{
_logger.LogWarning(e, "Failed to invoke middleware action {name}", name);
_logger.WriteWarning($"Failed to invoke middleware action {name}");
_logger.WriteDebug(e.GetExceptionInfo());
}
}

View File

@ -5,12 +5,9 @@ using System.Reflection;
using SharedLibraryCore.Interfaces;
using System.Linq;
using SharedLibraryCore;
using IW4MAdmin.Application.API.Master;
using Microsoft.Extensions.Logging;
using SharedLibraryCore.Configuration;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using IW4MAdmin.Application.Misc;
namespace IW4MAdmin.Application.Misc
namespace IW4MAdmin.Application.Helpers
{
/// <summary>
/// implementation of IPluginImporter
@ -18,19 +15,12 @@ namespace IW4MAdmin.Application.Misc
/// </summary>
public class PluginImporter : IPluginImporter
{
private IEnumerable<PluginSubscriptionContent> _pluginSubscription;
private static readonly string PLUGIN_DIR = "Plugins";
private readonly ILogger _logger;
private readonly IRemoteAssemblyHandler _remoteAssemblyHandler;
private readonly IMasterApi _masterApi;
private readonly ApplicationConfiguration _appConfig;
public PluginImporter(ILogger<PluginImporter> logger, ApplicationConfiguration appConfig, IMasterApi masterApi, IRemoteAssemblyHandler remoteAssemblyHandler)
public PluginImporter(ILogger logger)
{
_logger = logger;
_masterApi = masterApi;
_remoteAssemblyHandler = remoteAssemblyHandler;
_appConfig = appConfig;
}
/// <summary>
@ -43,16 +33,16 @@ namespace IW4MAdmin.Application.Misc
if (Directory.Exists(pluginDir))
{
var scriptPluginFiles = Directory.GetFiles(pluginDir, "*.js").AsEnumerable().Union(GetRemoteScripts());
string[] scriptPluginFiles = Directory.GetFiles(pluginDir, "*.js");
_logger.LogDebug("Discovered {count} potential script plugins", scriptPluginFiles.Count());
_logger.WriteInfo($"Discovered {scriptPluginFiles.Length} potential script plugins");
if (scriptPluginFiles.Count() > 0)
if (scriptPluginFiles.Length > 0)
{
foreach (string fileName in scriptPluginFiles)
{
_logger.LogDebug("Discovered script plugin {fileName}", fileName);
var plugin = new ScriptPlugin(_logger, fileName);
_logger.WriteInfo($"Discovered script plugin {fileName}");
var plugin = new ScriptPlugin(fileName);
yield return plugin;
}
}
@ -63,87 +53,36 @@ namespace IW4MAdmin.Application.Misc
/// discovers all the C# assembly plugins and commands
/// </summary>
/// <returns></returns>
public (IEnumerable<Type>, IEnumerable<Type>, IEnumerable<Type>) DiscoverAssemblyPluginImplementations()
public (IEnumerable<Type>, IEnumerable<Type>) DiscoverAssemblyPluginImplementations()
{
var pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}";
string pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}";
var pluginTypes = Enumerable.Empty<Type>();
var commandTypes = Enumerable.Empty<Type>();
var configurationTypes = Enumerable.Empty<Type>();
if (Directory.Exists(pluginDir))
{
var dllFileNames = Directory.GetFiles(pluginDir, "*.dll");
_logger.LogDebug("Discovered {count} potential plugin assemblies", dllFileNames.Length);
_logger.WriteInfo($"Discovered {dllFileNames.Length} potential plugin assemblies");
if (dllFileNames.Length > 0)
{
// we only want to load the most recent assembly in case of duplicates
var assemblies = dllFileNames.Select(_name => Assembly.LoadFrom(_name))
.Union(GetRemoteAssemblies())
.GroupBy(_assembly => _assembly.FullName).Select(_assembly => _assembly.OrderByDescending(_assembly => _assembly.GetName().Version).First());
var assemblies = dllFileNames.Select(_name => Assembly.LoadFrom(_name));
pluginTypes = assemblies
.SelectMany(_asm => _asm.GetTypes())
.Where(_assemblyType => _assemblyType.GetInterface(nameof(IPlugin), false) != null);
_logger.LogDebug("Discovered {count} plugin implementations", pluginTypes.Count());
_logger.WriteInfo($"Discovered {pluginTypes.Count()} plugin implementations");
commandTypes = assemblies
.SelectMany(_asm => _asm.GetTypes())
.Where(_assemblyType => _assemblyType.IsClass && _assemblyType.BaseType == typeof(Command));
_logger.LogDebug("Discovered {count} plugin commands", commandTypes.Count());
configurationTypes = assemblies
.SelectMany(asm => asm.GetTypes())
.Where(asmType =>
asmType.IsClass && asmType.GetInterface(nameof(IBaseConfiguration), false) != null);
_logger.LogDebug("Discovered {count} configuration implementations", configurationTypes.Count());
_logger.WriteInfo($"Discovered {commandTypes.Count()} plugin commands");
}
}
return (pluginTypes, commandTypes, configurationTypes);
return (pluginTypes, commandTypes);
}
private IEnumerable<Assembly> GetRemoteAssemblies()
{
try
{
if (_pluginSubscription == null)
_pluginSubscription = _masterApi.GetPluginSubscription(Guid.Parse(_appConfig.Id), _appConfig.SubscriptionId).Result;
return _remoteAssemblyHandler.DecryptAssemblies(_pluginSubscription.Where(sub => sub.Type == PluginType.Binary).Select(sub => sub.Content).ToArray());
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Could not load remote assemblies");
return Enumerable.Empty<Assembly>();
}
}
private IEnumerable<string> GetRemoteScripts()
{
try
{
if (_pluginSubscription == null)
_pluginSubscription = _masterApi.GetPluginSubscription(Guid.Parse(_appConfig.Id), _appConfig.SubscriptionId).Result;
return _remoteAssemblyHandler.DecryptScripts(_pluginSubscription.Where(sub => sub.Type == PluginType.Script).Select(sub => sub.Content).ToArray());
}
catch (Exception ex)
{
_logger.LogWarning(ex,"Could not load remote scripts");
return Enumerable.Empty<string>();
}
}
}
public enum PluginType
{
Binary,
Script
}
}

View File

@ -1,76 +0,0 @@
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
public class RemoteAssemblyHandler : IRemoteAssemblyHandler
{
private const int keyLength = 32;
private const int tagLength = 16;
private const int nonceLength = 12;
private const int iterationCount = 10000;
private readonly ApplicationConfiguration _appconfig;
private readonly ILogger _logger;
public RemoteAssemblyHandler(ILogger<RemoteAssemblyHandler> logger, ApplicationConfiguration appconfig)
{
_appconfig = appconfig;
_logger = logger;
}
public IEnumerable<Assembly> DecryptAssemblies(string[] encryptedAssemblies)
{
return DecryptContent(encryptedAssemblies)
.Select(decryptedAssembly => Assembly.Load(decryptedAssembly));
}
public IEnumerable<string> DecryptScripts(string[] encryptedScripts)
{
return DecryptContent(encryptedScripts).Select(decryptedScript => Encoding.UTF8.GetString(decryptedScript));
}
private byte[][] DecryptContent(string[] content)
{
if (string.IsNullOrEmpty(_appconfig.Id) || string.IsNullOrWhiteSpace(_appconfig.SubscriptionId))
{
_logger.LogWarning($"{nameof(_appconfig.Id)} and {nameof(_appconfig.SubscriptionId)} must be provided to attempt loading remote assemblies/scripts");
return new byte[0][];
}
var assemblies = content.Select(piece =>
{
byte[] byteContent = Convert.FromBase64String(piece);
byte[] encryptedContent = byteContent.Take(byteContent.Length - (tagLength + nonceLength)).ToArray();
byte[] tag = byteContent.Skip(byteContent.Length - (tagLength + nonceLength)).Take(tagLength).ToArray();
byte[] nonce = byteContent.Skip(byteContent.Length - nonceLength).Take(nonceLength).ToArray();
byte[] decryptedContent = new byte[encryptedContent.Length];
var keyGen = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(_appconfig.SubscriptionId), Encoding.UTF8.GetBytes(_appconfig.Id.ToString()), iterationCount, HashAlgorithmName.SHA512);
var encryption = new AesGcm(keyGen.GetBytes(keyLength));
try
{
encryption.Decrypt(nonce, encryptedContent, tag, decryptedContent);
}
catch (CryptographicException ex)
{
_logger.LogError(ex, "Could not decrypt remote plugin assemblies");
}
return decryptedContent;
});
return assemblies.ToArray();
}
}
}

View File

@ -4,10 +4,7 @@ using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using System;
using System.Threading.Tasks;
using Data.Models.Client;
using Microsoft.Extensions.Logging;
using static SharedLibraryCore.Database.Models.EFClient;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
@ -17,15 +14,13 @@ namespace IW4MAdmin.Application.Misc
public class ScriptCommand : Command
{
private readonly Action<GameEvent> _executeAction;
private readonly ILogger _logger;
public ScriptCommand(string name, string alias, string description, bool isTargetRequired, EFClient.Permission permission,
CommandArgument[] args, Action<GameEvent> executeAction, CommandConfiguration config, ITranslationLookup layout, ILogger<ScriptCommand> logger)
public ScriptCommand(string name, string alias, string description, bool isTargetRequired, Permission permission,
CommandArgument[] args, Action<GameEvent> executeAction, CommandConfiguration config, ITranslationLookup layout)
: base(config, layout)
{
_executeAction = executeAction;
_logger = logger;
Name = name;
Alias = alias;
Description = description;
@ -34,21 +29,14 @@ namespace IW4MAdmin.Application.Misc
Arguments = args;
}
public override async Task ExecuteAsync(GameEvent e)
public override Task ExecuteAsync(GameEvent E)
{
if (_executeAction == null)
{
throw new InvalidOperationException($"No execute action defined for command \"{Name}\"");
}
try
{
await Task.Run(() => _executeAction(e));
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to execute ScriptCommand action for command {command} {@event}", Name, e);
}
return Task.Run(() => _executeAction(E));
}
}
}

View File

@ -1,5 +1,4 @@
using System;
using Jint;
using Jint;
using Jint.Native;
using Jint.Runtime;
using Microsoft.CSharp.RuntimeBinder;
@ -13,9 +12,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
@ -43,11 +39,9 @@ namespace IW4MAdmin.Application.Misc
private readonly SemaphoreSlim _onProcessing;
private bool successfullyLoaded;
private readonly List<string> _registeredCommandNames;
private readonly ILogger _logger;
public ScriptPlugin(ILogger logger, string filename, string workingDirectory = null)
public ScriptPlugin(string filename, string workingDirectory = null)
{
_logger = logger;
_fileName = filename;
Watcher = new FileSystemWatcher()
{
@ -90,7 +84,7 @@ namespace IW4MAdmin.Application.Misc
foreach (string commandName in _registeredCommandNames)
{
_logger.LogDebug("Removing plugin registered command {command}", commandName);
manager.GetLogger(0).WriteDebug($"Removing plugin registered command \"{commandName}\"");
manager.RemoveCommandByName(commandName);
}
@ -118,28 +112,7 @@ namespace IW4MAdmin.Application.Misc
})
.CatchClrExceptions());
try
{
_scriptEngine.Execute(script);
}
catch (JavaScriptException ex)
{
_logger.LogError(ex,
"Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} at {@locationInfo}",
nameof(Initialize), _fileName, ex.Location);
throw new PluginException($"A JavaScript parsing error occured while initializing script plugin");
}
catch (Exception e)
{
_logger.LogError(e,
"Encountered unexpected error while running {methodName} for script plugin {plugin}",
nameof(Initialize), _fileName);
throw new PluginException($"An unexpected error occured while initialization script plugin");
}
_scriptEngine.Execute(script);
_scriptEngine.SetValue("_localization", Utilities.CurrentLocalization);
_scriptEngine.SetValue("_serviceResolver", serviceResolver);
dynamic pluginObject = _scriptEngine.GetValue("plugin").ToObject();
@ -156,7 +129,7 @@ namespace IW4MAdmin.Application.Misc
{
foreach (var command in GenerateScriptCommands(commands, scriptCommandFactory))
{
_logger.LogDebug("Adding plugin registered command {commandName}", command.Name);
manager.GetLogger(0).WriteDebug($"Adding plugin registered command \"{command.Name}\"");
manager.AddAdditionalCommand(command);
_registeredCommandNames.Add(command.Name);
}
@ -168,7 +141,6 @@ namespace IW4MAdmin.Application.Misc
}
}
_scriptEngine.SetValue("_configHandler", new ScriptPluginConfigurationWrapper(Name, _scriptEngine));
await OnLoadAsync(manager);
try
@ -195,20 +167,12 @@ namespace IW4MAdmin.Application.Misc
catch (JavaScriptException ex)
{
_logger.LogError(ex,
"Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} initialization {@locationInfo}",
nameof(OnLoadAsync), _fileName, ex.Location);
throw new PluginException("An error occured while initializing script plugin");
throw new PluginException($"An error occured while initializing script plugin: {ex.Error} (Line: {ex.Location.Start.Line}, Character: {ex.Location.Start.Column})") { PluginFile = _fileName };
}
catch (Exception ex)
catch
{
_logger.LogError(ex,
"Encountered unexpected error while running {methodName} for script plugin {plugin}",
nameof(OnLoadAsync), _fileName);
throw new PluginException("An unexpected error occured while initializing script plugin");
throw;
}
finally
@ -234,28 +198,9 @@ namespace IW4MAdmin.Application.Misc
_scriptEngine.Execute("plugin.onEventAsync(_gameEvent, _server)").GetCompletionValue();
}
catch (JavaScriptException ex)
catch
{
using (LogContext.PushProperty("Server", S.ToString()))
{
_logger.LogError(ex,
"Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} with event type {eventType} {@locationInfo}",
nameof(OnEventAsync), _fileName, E.Type, ex.Location);
}
throw new PluginException($"An error occured while executing action for script plugin");
}
catch (Exception e)
{
using (LogContext.PushProperty("Server", S.ToString()))
{
_logger.LogError(e,
"Encountered unexpected error while running {methodName} for script plugin {plugin} with event type {eventType}",
nameof(OnEventAsync), _fileName, E.Type);
}
throw new PluginException($"An error occured while executing action for script plugin");
throw;
}
finally
@ -270,7 +215,7 @@ namespace IW4MAdmin.Application.Misc
public Task OnLoadAsync(IManager manager)
{
_logger.LogDebug("OnLoad executing for {name}", Name);
manager.GetLogger(0).WriteDebug($"OnLoad executing for {Name}");
_scriptEngine.SetValue("_manager", manager);
return Task.FromResult(_scriptEngine.Execute("plugin.onLoadAsync(_manager)").GetCompletionValue());
}

View File

@ -1,90 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using IW4MAdmin.Application.Configuration;
using Jint;
using Jint.Native;
using Newtonsoft.Json.Linq;
namespace IW4MAdmin.Application.Misc
{
public class ScriptPluginConfigurationWrapper
{
private readonly BaseConfigurationHandler<ScriptPluginConfiguration> _handler;
private readonly ScriptPluginConfiguration _config;
private readonly string _pluginName;
private readonly Engine _scriptEngine;
public ScriptPluginConfigurationWrapper(string pluginName, Engine scriptEngine)
{
_handler = new BaseConfigurationHandler<ScriptPluginConfiguration>("ScriptPluginSettings");
_config = _handler.Configuration() ??
(ScriptPluginConfiguration) new ScriptPluginConfiguration().Generate();
_pluginName = pluginName;
_scriptEngine = scriptEngine;
}
private static int? AsInteger(double d)
{
return int.TryParse(d.ToString(CultureInfo.InvariantCulture), out var parsed) ? parsed : (int?) null;
}
public async Task SetValue(string key, object value)
{
var castValue = value;
if (value is double d)
{
castValue = AsInteger(d) ?? value;
}
if (value is object[] array && array.All(item => item is double d && AsInteger(d) != null))
{
castValue = array.Select(item => AsInteger((double)item)).ToArray();
}
if (!_config.ContainsKey(_pluginName))
{
_config.Add(_pluginName, new Dictionary<string, object>());
}
var plugin = _config[_pluginName];
if (plugin.ContainsKey(key))
{
plugin[key] = castValue;
}
else
{
plugin.Add(key, castValue);
}
_handler.Set(_config);
await _handler.Save();
}
public JsValue GetValue(string key)
{
if (!_config.ContainsKey(_pluginName))
{
return JsValue.Undefined;
}
if (!_config[_pluginName].ContainsKey(key))
{
return JsValue.Undefined;
}
var item = _config[_pluginName][key];
if (item is JArray array)
{
item = array.ToObject<List<dynamic>>();
}
return JsValue.FromObject(_scriptEngine, item);
}
}
}

View File

@ -4,7 +4,6 @@ using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using System;
using System.Net;
using Data.Models;
using static SharedLibraryCore.Database.Models.EFClient;
using static SharedLibraryCore.GameEvent;

View File

@ -1,147 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models;
using Data.Models.Client;
using Data.Models.Client.Stats.Reference;
using Data.Models.Server;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.Misc
{
/// <inheritdoc/>
public class ServerDataCollector : IServerDataCollector
{
private readonly ILogger _logger;
private readonly IManager _manager;
private readonly IDatabaseContextFactory _contextFactory;
private readonly ApplicationConfiguration _appConfig;
private readonly IEventPublisher _eventPublisher;
private bool _inProgress;
private TimeSpan _period;
public ServerDataCollector(ILogger<ServerDataCollector> logger, ApplicationConfiguration appConfig,
IManager manager, IDatabaseContextFactory contextFactory, IEventPublisher eventPublisher)
{
_logger = logger;
_appConfig = appConfig;
_manager = manager;
_contextFactory = contextFactory;
_eventPublisher = eventPublisher;
_eventPublisher.OnClientConnect += SaveConnectionInfo;
_eventPublisher.OnClientDisconnect += SaveConnectionInfo;
}
~ServerDataCollector()
{
_eventPublisher.OnClientConnect -= SaveConnectionInfo;
_eventPublisher.OnClientDisconnect -= SaveConnectionInfo;
}
public async Task BeginCollectionAsync(TimeSpan? period = null, CancellationToken cancellationToken = default)
{
if (_inProgress)
{
throw new InvalidOperationException($"{nameof(ServerDataCollector)} is already collecting data");
}
_logger.LogDebug("Initializing data collection with {Name}", nameof(ServerDataCollector));
_inProgress = true;
_period = period ?? (Utilities.IsDevelopment
? TimeSpan.FromMinutes(1)
: _appConfig.ServerDataCollectionInterval);
while (!cancellationToken.IsCancellationRequested)
{
try
{
await Task.Delay(_period, cancellationToken);
_logger.LogDebug("{Name} is collecting server data", nameof(ServerDataCollector));
var data = await BuildCollectionData(cancellationToken);
await SaveData(data, cancellationToken);
}
catch (TaskCanceledException)
{
_logger.LogInformation("Shutdown requested for {Name}", nameof(ServerDataCollector));
return;
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error encountered collecting server data for {Name}",
nameof(ServerDataCollector));
}
}
}
private async Task<IEnumerable<EFServerSnapshot>> BuildCollectionData(CancellationToken token)
{
var data = await Task.WhenAll(_manager.GetServers()
.Select(async server => new EFServerSnapshot
{
CapturedAt = DateTime.UtcNow,
PeriodBlock = (int) (DateTimeOffset.UtcNow - DateTimeOffset.UnixEpoch).TotalMinutes,
ServerId = await server.GetIdForServer(),
MapId = await GetOrCreateMap(server.CurrentMap.Name, (Reference.Game) server.GameName, token),
ClientCount = server.ClientNum
}));
return data;
}
private async Task<int> GetOrCreateMap(string mapName, Reference.Game game, CancellationToken token)
{
await using var context = _contextFactory.CreateContext();
var existingMap =
await context.Maps.FirstOrDefaultAsync(map => map.Name == mapName && map.Game == game, token);
if (existingMap != null)
{
return existingMap.MapId;
}
var newMap = new EFMap
{
Name = mapName,
Game = game
};
context.Maps.Add(newMap);
await context.SaveChangesAsync(token);
return newMap.MapId;
}
private async Task SaveData(IEnumerable<EFServerSnapshot> snapshots, CancellationToken token)
{
await using var context = _contextFactory.CreateContext();
context.ServerSnapshots.AddRange(snapshots);
await context.SaveChangesAsync(token);
}
private void SaveConnectionInfo(object sender, GameEvent gameEvent)
{
using var context = _contextFactory.CreateContext(enableTracking: false);
context.ConnectionHistory.Add(new EFClientConnectionHistory
{
ClientId = gameEvent.Origin.ClientId,
ServerId = gameEvent.Owner.GetIdForServer().Result,
ConnectionType = gameEvent.Type == GameEvent.EventType.Connect
? Reference.ConnectionType.Connect
: Reference.ConnectionType.Disconnect
});
context.SaveChanges();
}
}
}

View File

@ -1,161 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models.Client;
using Data.Models.Server;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc
{
/// <inheritdoc/>
public class ServerDataViewer : IServerDataViewer
{
private readonly ILogger _logger;
private readonly IDataValueCache<EFServerSnapshot, (int?, DateTime?)> _snapshotCache;
private readonly IDataValueCache<EFClient, (int, int)> _serverStatsCache;
private readonly IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> _clientHistoryCache;
private readonly TimeSpan? _cacheTimeSpan =
Utilities.IsDevelopment ? TimeSpan.FromSeconds(1) : (TimeSpan?) TimeSpan.FromMinutes(1);
public ServerDataViewer(ILogger<ServerDataViewer> logger, IDataValueCache<EFServerSnapshot, (int?, DateTime?)> snapshotCache,
IDataValueCache<EFClient, (int, int)> serverStatsCache,
IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> clientHistoryCache)
{
_logger = logger;
_snapshotCache = snapshotCache;
_serverStatsCache = serverStatsCache;
_clientHistoryCache = clientHistoryCache;
}
public async Task<(int?, DateTime?)> MaxConcurrentClientsAsync(long? serverId = null, TimeSpan? overPeriod = null,
CancellationToken token = default)
{
_snapshotCache.SetCacheItem(async (snapshots, cancellationToken) =>
{
var oldestEntry = overPeriod.HasValue
? DateTime.UtcNow - overPeriod.Value
: DateTime.UtcNow.AddDays(-1);
int? maxClients;
DateTime? maxClientsTime;
if (serverId != null)
{
var clients = await snapshots.Where(snapshot => snapshot.ServerId == serverId)
.Where(snapshot => snapshot.CapturedAt >= oldestEntry)
.OrderByDescending(snapshot => snapshot.ClientCount)
.Select(snapshot => new
{
snapshot.ClientCount,
snapshot.CapturedAt
})
.FirstOrDefaultAsync(cancellationToken);
maxClients = clients?.ClientCount;
maxClientsTime = clients?.CapturedAt;
}
else
{
var clients = await snapshots.Where(snapshot => snapshot.CapturedAt >= oldestEntry)
.GroupBy(snapshot => snapshot.PeriodBlock)
.Select(grp => new
{
ClientCount = grp.Sum(snapshot => (int?) snapshot.ClientCount),
Time = grp.Max(snapshot => (DateTime?) snapshot.CapturedAt)
})
.OrderByDescending(snapshot => snapshot.ClientCount)
.FirstOrDefaultAsync(cancellationToken);
maxClients = clients?.ClientCount;
maxClientsTime = clients?.Time;
}
_logger.LogDebug("Max concurrent clients since {Start} is {Clients}", oldestEntry, maxClients);
return (maxClients, maxClientsTime);
}, nameof(MaxConcurrentClientsAsync), _cacheTimeSpan);
try
{
return await _snapshotCache.GetCacheItem(nameof(MaxConcurrentClientsAsync), token);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not retrieve data for {Name}", nameof(MaxConcurrentClientsAsync));
return (null, null);
}
}
public async Task<(int, int)> ClientCountsAsync(TimeSpan? overPeriod = null, CancellationToken token = default)
{
_serverStatsCache.SetCacheItem(async (set, cancellationToken) =>
{
var count = await set.CountAsync(cancellationToken);
var startOfPeriod =
DateTime.UtcNow.AddHours(-overPeriod?.TotalHours ?? -24);
var recentCount = await set.CountAsync(client => client.LastConnection >= startOfPeriod,
cancellationToken);
return (count, recentCount);
}, nameof(_serverStatsCache), _cacheTimeSpan);
try
{
return await _serverStatsCache.GetCacheItem(nameof(_serverStatsCache), token);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not retrieve data for {Name}", nameof(ClientCountsAsync));
return (0, 0);
}
}
public async Task<IEnumerable<ClientHistoryInfo>> ClientHistoryAsync(TimeSpan? overPeriod = null, CancellationToken token = default)
{
_clientHistoryCache.SetCacheItem(async (set, cancellationToken) =>
{
var oldestEntry = overPeriod.HasValue
? DateTime.UtcNow - overPeriod.Value
: DateTime.UtcNow.AddHours(-12);
var history = await set.Where(snapshot => snapshot.CapturedAt >= oldestEntry)
.Select(snapshot =>
new
{
snapshot.ServerId,
snapshot.CapturedAt,
snapshot.ClientCount
})
.OrderBy(snapshot => snapshot.CapturedAt)
.ToListAsync(cancellationToken);
return history.GroupBy(snapshot => snapshot.ServerId).Select(byServer => new ClientHistoryInfo
{
ServerId = byServer.Key,
ClientCounts = byServer.Select(snapshot => new ClientCountSnapshot()
{Time = snapshot.CapturedAt, ClientCount = snapshot.ClientCount}).ToList()
}).ToList();
}, nameof(_clientHistoryCache), TimeSpan.MaxValue);
try
{
return await _clientHistoryCache.GetCacheItem(nameof(_clientHistoryCache), token);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not retrieve data for {Name}", nameof(ClientHistoryAsync));
return Enumerable.Empty<ClientHistoryInfo>();
}
}
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
namespace Integrations.Cod
namespace IW4MAdmin.Application.RCon
{
/// <summary>
/// used to keep track of the udp connection state
@ -18,7 +18,7 @@ namespace Integrations.Cod
}
public int ConnectionAttempts { get; set; }
private const int BufferSize = 16384;
const int BufferSize = 4096;
public readonly byte[] ReceiveBuffer = new byte[BufferSize];
public readonly SemaphoreSlim OnComplete = new SemaphoreSlim(1, 1);
public readonly ManualResetEventSlim OnSentData = new ManualResetEventSlim(false);

View File

@ -1,4 +1,8 @@
using System;
using SharedLibraryCore;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.RCon;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@ -6,44 +10,34 @@ using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using SharedLibraryCore;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.RCon;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Integrations.Cod
namespace IW4MAdmin.Application.RCon
{
/// <summary>
/// implementation of IRConConnection
/// </summary>
public class CodRConConnection : IRConConnection
public class RConConnection : IRConConnection
{
static readonly ConcurrentDictionary<EndPoint, ConnectionState> ActiveQueries = new ConcurrentDictionary<EndPoint, ConnectionState>();
public IPEndPoint Endpoint { get; }
public string RConPassword { get; }
public IPEndPoint Endpoint { get; private set; }
public string RConPassword { get; private set; }
private IRConParser parser;
private IRConParserConfiguration config;
private readonly ILogger _log;
private readonly Encoding _gameEncoding;
public CodRConConnection(IPEndPoint ipEndpoint, string password, ILogger<CodRConConnection> log, Encoding gameEncoding)
public RConConnection(string ipAddress, int port, string password, ILogger log, Encoding gameEncoding)
{
RConPassword = password;
Endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
_gameEncoding = gameEncoding;
RConPassword = password;
_log = log;
Endpoint = ipEndpoint;
}
public void SetConfiguration(IRConParser parser)
public void SetConfiguration(IRConParserConfiguration config)
{
this.parser = parser;
config = parser.Configuration;
this.config = config;
}
public async Task<string[]> SendQueryAsync(StaticHelpers.QueryType type, string parameters = "")
@ -55,8 +49,9 @@ namespace Integrations.Cod
var connectionState = ActiveQueries[this.Endpoint];
_log.LogDebug("Waiting for semaphore to be released [{endpoint}]", Endpoint);
#if DEBUG == true
_log.WriteDebug($"Waiting for semaphore to be released [{this.Endpoint}]");
#endif
// enter the semaphore so only one query is sent at a time per server.
await connectionState.OnComplete.WaitAsync();
@ -69,8 +64,10 @@ namespace Integrations.Cod
connectionState.LastQuery = DateTime.Now;
_log.LogDebug("Semaphore has been released [{endpoint}]", Endpoint);
_log.LogDebug("Query {@queryInfo}", new { endpoint=Endpoint.ToString(), type, parameters });
#if DEBUG == true
_log.WriteDebug($"Semaphore has been released [{this.Endpoint}]");
_log.WriteDebug($"Query [{this.Endpoint},{type.ToString()},{parameters}]");
#endif
byte[] payload = null;
bool waitForResponse = config.WaitForResponse;
@ -115,34 +112,18 @@ namespace Integrations.Cod
// this happens when someone tries to send something that can't be converted into a 7 bit character set
// e.g: emoji -> windows-1252
catch (OverflowException ex)
catch (OverflowException)
{
connectionState.OnComplete.Release(1);
using (LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogError(ex, "Could not convert RCon data payload to desired encoding {encoding} {params}",
_gameEncoding.EncodingName, parameters);
}
throw new RConException($"Invalid character encountered when converting encodings");
throw new NetworkException($"Invalid character encountered when converting encodings - {parameters}");
}
byte[][] response = null;
retrySend:
if (connectionState.ConnectionAttempts > 1)
{
using (LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogInformation(
"Retrying RCon message ({connectionAttempts}/{allowedConnectionFailures} attempts) with parameters {payload}",
connectionState.ConnectionAttempts,
StaticHelpers.AllowedConnectionFails, parameters);
}
}
retrySend:
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
{
DontFragment = false,
DontFragment = true,
Ttl = 100,
ExclusiveAddressUse = true,
})
@ -152,19 +133,16 @@ namespace Integrations.Cod
connectionState.OnReceivedData.Reset();
connectionState.ConnectionAttempts++;
connectionState.BytesReadPerSegment.Clear();
bool exceptionCaught = false;
_log.LogDebug("Sending {payloadLength} bytes to [{endpoint}] ({connectionAttempts}/{allowedConnectionFailures})",
payload.Length, Endpoint, connectionState.ConnectionAttempts, StaticHelpers.AllowedConnectionFails);
#if DEBUG == true
_log.WriteDebug($"Sending {payload.Length} bytes to [{this.Endpoint}] ({connectionState.ConnectionAttempts}/{StaticHelpers.AllowedConnectionFails})");
#endif
try
{
response = await SendPayloadAsync(payload, waitForResponse, parser.OverrideTimeoutForCommand(parameters));
response = await SendPayloadAsync(payload, waitForResponse);
if ((response.Length == 0 || response[0].Length == 0) && waitForResponse)
{
throw new RConException("Expected response but got 0 bytes back");
throw new NetworkException("Expected response but got 0 bytes back");
}
connectionState.ConnectionAttempts = 0;
@ -172,28 +150,18 @@ namespace Integrations.Cod
catch
{
// we want to retry with a delay
if (connectionState.ConnectionAttempts < StaticHelpers.AllowedConnectionFails)
{
exceptionCaught = true;
await Task.Delay(StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts));
await Task.Delay(StaticHelpers.FloodProtectionInterval);
goto retrySend;
}
using (LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogWarning(
"Made {connectionAttempts} attempts to send RCon data to server, but received no response",
connectionState.ConnectionAttempts);
}
connectionState.ConnectionAttempts = 0;
throw new NetworkException("Reached maximum retry attempts to send RCon data to server");
throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMUNICATION"].FormatExt(Endpoint));
}
finally
{
// we don't want to release if we're going to retry the query
if (connectionState.OnComplete.CurrentCount == 0 && !exceptionCaught)
if (connectionState.OnComplete.CurrentCount == 0)
{
connectionState.OnComplete.Release(1);
}
@ -202,22 +170,23 @@ namespace Integrations.Cod
if (response.Length == 0)
{
_log.LogDebug("Received empty response for RCon request {@query}", new { endpoint=Endpoint.ToString(), type, parameters });
_log.WriteWarning($"Received empty response for request [{type.ToString()}, {parameters}, {Endpoint.ToString()}]");
return new string[0];
}
string responseString = type == StaticHelpers.QueryType.COMMAND_STATUS ?
ReassembleSegmentedStatus(response) : RecombineMessages(response);
ReassembleSegmentedStatus(response) :
_gameEncoding.GetString(response[0]) + '\n';
// note: not all games respond if the pasword is wrong or not set
if (responseString.Contains("Invalid password") || responseString.Contains("rconpassword"))
{
throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]);
throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]);
}
if (responseString.Contains("rcon_password"))
{
throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]);
throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]);
}
if (responseString.Contains(config.ServerNotRunningResponse))
@ -230,13 +199,7 @@ namespace Integrations.Cod
if (headerSplit.Length != 2)
{
using (LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogWarning("Invalid response header from server. Expected {expected}, but got {response}",
config.CommandPrefixes.RConResponse, headerSplit.FirstOrDefault());
}
throw new RConException("Unexpected response header from server");
throw new NetworkException("Unexpected response header from server");
}
string[] splitResponse = headerSplit.Last().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
@ -271,36 +234,7 @@ namespace Integrations.Cod
return string.Join("", splitStatusStrings);
}
/// <summary>
/// Recombines multiple game messages into one
/// </summary>
/// <param name="payload"></param>
/// <returns></returns>
private string RecombineMessages(byte[][] payload)
{
if (payload.Length == 1)
{
return _gameEncoding.GetString(payload[0]).TrimEnd('\n') + '\n';
}
else
{
var builder = new StringBuilder();
for (int i = 0; i < payload.Length; i++)
{
string message = _gameEncoding.GetString(payload[i]).TrimEnd('\n') + '\n';
if (i > 0)
{
message = message.Replace(config.CommandPrefixes.RConResponse, "");
}
builder.Append(message);
}
builder.Append('\n');
return builder.ToString();
}
}
private async Task<byte[][]> SendPayloadAsync(byte[] payload, bool waitForResponse, TimeSpan overrideTimeout)
private async Task<byte[][]> SendPayloadAsync(byte[] payload, bool waitForResponse)
{
var connectionState = ActiveQueries[this.Endpoint];
var rconSocket = (Socket)connectionState.SendEventArgs.UserToken;
@ -324,17 +258,11 @@ namespace Integrations.Cod
if (sendDataPending)
{
// the send has not been completed asynchronously
// this really shouldn't ever happen because it's UDP
if (!await Task.Run(() => connectionState.OnSentData.Wait(StaticHelpers.SocketTimeout(1))))
// the send has not been completed asyncronously
if (!await Task.Run(() => connectionState.OnSentData.Wait(StaticHelpers.SocketTimeout)))
{
using(LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogWarning("Socket timed out while sending RCon data on attempt {attempt}",
connectionState.ConnectionAttempts);
}
rconSocket.Close();
throw new NetworkException("Timed out sending RCon data", rconSocket);
throw new NetworkException("Timed out sending data", rconSocket);
}
}
@ -350,37 +278,15 @@ namespace Integrations.Cod
if (receiveDataPending)
{
_log.LogDebug("Waiting to asynchronously receive data on attempt #{connectionAttempts}", connectionState.ConnectionAttempts);
if (!await Task.Run(() => connectionState.OnReceivedData.Wait(
new[]
{
StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts),
overrideTimeout
}.Max())))
if (!await Task.Run(() => connectionState.OnReceivedData.Wait(10000)))
{
if (connectionState.ConnectionAttempts > 1) // this reduces some spam for unstable connections
{
using (LogContext.PushProperty("Server", Endpoint.ToString()))
{
_log.LogWarning(
"Socket timed out while waiting for RCon response on attempt {attempt} with timeout delay of {timeout}",
connectionState.ConnectionAttempts,
StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts));
}
}
rconSocket.Close();
throw new NetworkException("Timed out receiving RCon response", rconSocket);
throw new NetworkException("Timed out waiting for response", rconSocket);
}
}
rconSocket.Close();
return GetResponseData(connectionState);
}
private byte[][] GetResponseData(ConnectionState connectionState)
{
var responseList = new List<byte[]>();
int totalBytesRead = 0;
@ -399,72 +305,58 @@ namespace Integrations.Cod
private void OnDataReceived(object sender, SocketAsyncEventArgs e)
{
_log.LogDebug("Read {bytesTransferred} bytes from {endpoint}", e.BytesTransferred, e.RemoteEndPoint);
#if DEBUG == true
_log.WriteDebug($"Read {e.BytesTransferred} bytes from {e.RemoteEndPoint.ToString()}");
#endif
// this occurs when we close the socket
if (e.BytesTransferred == 0)
{
_log.LogDebug("No bytes were transmitted so the connection was probably closed");
ActiveQueries[this.Endpoint].OnReceivedData.Set();
return;
}
if (!(sender is Socket sock))
if (sender is Socket sock)
{
return;
}
var state = ActiveQueries[this.Endpoint];
state.BytesReadPerSegment.Add(e.BytesTransferred);
var state = ActiveQueries[this.Endpoint];
state.BytesReadPerSegment.Add(e.BytesTransferred);
// I don't even want to know why this works for getting more data from Cod4x
// but I'm leaving it in here as long as it doesn't break anything.
// it's very stupid...
Thread.Sleep(150);
try
{
var totalBytesTransferred = e.BytesTransferred;
_log.LogDebug("{total} total bytes transferred with {available} bytes remaining", totalBytesTransferred, sock.Available);
// we still have available data so the payload was segmented
while (sock.Available > 0)
try
{
_log.LogDebug("{available} more bytes to be read", sock.Available);
var bufferSpaceAvailable = sock.Available + totalBytesTransferred - state.ReceiveBuffer.Length;
if (bufferSpaceAvailable >= 0 )
// we still have available data so the payload was segmented
if (sock.Available > 0)
{
_log.LogWarning("Not enough buffer space to store incoming data {bytesNeeded} additional bytes required", bufferSpaceAvailable);
continue;
state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, e.BytesTransferred, state.ReceiveBuffer.Length - e.BytesTransferred);
if (!sock.ReceiveAsync(state.ReceiveEventArgs))
{
#if DEBUG == true
_log.WriteDebug($"Read {state.ReceiveEventArgs.BytesTransferred} synchronous bytes from {e.RemoteEndPoint.ToString()}");
#endif
// we need to increment this here because the callback isn't executed if there's no pending IO
state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred);
ActiveQueries[this.Endpoint].OnReceivedData.Set();
}
}
state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available);
if (sock.ReceiveAsync(state.ReceiveEventArgs))
else
{
_log.LogDebug("Remaining bytes are async");
continue;
ActiveQueries[this.Endpoint].OnReceivedData.Set();
}
_log.LogDebug("Read {bytesTransferred} synchronous bytes from {endpoint}", state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint);
// we need to increment this here because the callback isn't executed if there's no pending IO
state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred);
totalBytesTransferred += state.ReceiveEventArgs.BytesTransferred;
}
ActiveQueries[this.Endpoint].OnReceivedData.Set();
}
catch (ObjectDisposedException)
{
_log.LogDebug("Socket was disposed while receiving data");
ActiveQueries[this.Endpoint].OnReceivedData.Set();
catch (ObjectDisposedException)
{
ActiveQueries[this.Endpoint].OnReceivedData.Set();
}
}
}
private void OnDataSent(object sender, SocketAsyncEventArgs e)
{
_log.LogDebug("Sent {byteCount} bytes to {endpoint}", e.Buffer?.Length, e.ConnectSocket?.RemoteEndPoint);
#if DEBUG == true
_log.WriteDebug($"Sent {e.Buffer?.Length} bytes to {e.ConnectSocket?.RemoteEndPoint?.ToString()}");
#endif
ActiveQueries[this.Endpoint].OnSentData.Set();
}
}

View File

@ -1,16 +0,0 @@
using Microsoft.Extensions.Logging;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.RConParsers
{
/// <summary>
/// empty implementation of the IW4RConParser
/// allows script plugins to generate dynamic RCon parsers
/// </summary>
internal sealed class DynamicRConParser : BaseRConParser
{
public DynamicRConParser(ILogger<BaseRConParser> logger, IParserRegexFactory parserRegexFactory) : base(logger, parserRegexFactory)
{
}
}
}

View File

@ -1,15 +0,0 @@
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.RConParsers
{
/// <inheritdoc cref="IStatusResponse"/>
public class StatusResponse : IStatusResponse
{
public string Map { get; set; }
public string GameType { get; set; }
public string Hostname { get; set; }
public int? MaxClients { get; set; }
public EFClient[] Clients { get; set; }
}
}

View File

@ -8,20 +8,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Data.Models;
using Microsoft.Extensions.Logging;
using static SharedLibraryCore.Server;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.RConParsers
namespace IW4MAdmin.Application.RconParsers
{
public class BaseRConParser : IRConParser
{
private readonly ILogger _logger;
public BaseRConParser(ILogger<BaseRConParser> logger, IParserRegexFactory parserRegexFactory)
public BaseRConParser(IParserRegexFactory parserRegexFactory)
{
_logger = logger;
Configuration = new DynamicRConParserConfiguration(parserRegexFactory)
{
CommandPrefixes = new CommandPrefix()
@ -56,7 +50,6 @@ namespace IW4MAdmin.Application.RConParsers
Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarDefaultValue, 3);
Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarLatchedValue, 4);
Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarDomain, 5);
Configuration.Dvar.AddMapping(ParserRegex.GroupType.AdditionalGroup, int.MaxValue);
Configuration.StatusHeader.Pattern = "num +score +ping +guid +name +lastmsg +address +qport +rate *";
Configuration.GametypeStatus.Pattern = "";
@ -74,33 +67,16 @@ namespace IW4MAdmin.Application.RConParsers
public Game GameName { get; set; } = Game.COD;
public bool CanGenerateLogPath { get; set; } = true;
public string Name { get; set; } = "Call of Duty";
public string RConEngine { get; set; } = "COD";
public bool IsOneLog { get; set; }
public async Task<string[]> ExecuteCommandAsync(IRConConnection connection, string command)
{
var response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command);
return response.Where(item => item != Configuration.CommandPrefixes.RConResponse).ToArray();
return response.Skip(1).ToArray();
}
public async Task<Dvar<T>> GetDvarAsync<T>(IRConConnection connection, string dvarName, T fallbackValue = default)
{
string[] lineSplit;
try
{
lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.GET_DVAR, dvarName);
}
catch
{
if (fallbackValue == null)
{
throw;
}
lineSplit = new string[0];
}
string[] lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.GET_DVAR, dvarName);
string response = string.Join('\n', lineSplit).TrimEnd('\0');
var match = Regex.Match(response, Configuration.Dvar.Pattern);
@ -131,7 +107,7 @@ namespace IW4MAdmin.Application.RConParsers
return new Dvar<T>()
{
Name = dvarName,
Name = match.Groups[Configuration.Dvar.GroupMapping[ParserRegex.GroupType.RConDvarName]].Value,
Value = string.IsNullOrEmpty(value) ? default : (T)Convert.ChangeType(value, typeof(T)),
DefaultValue = string.IsNullOrEmpty(defaultValue) ? default : (T)Convert.ChangeType(defaultValue, typeof(T)),
LatchedValue = string.IsNullOrEmpty(latchedValue) ? default : (T)Convert.ChangeType(latchedValue, typeof(T)),
@ -139,55 +115,58 @@ namespace IW4MAdmin.Application.RConParsers
};
}
public virtual async Task<IStatusResponse> GetStatusAsync(IRConConnection connection)
public virtual async Task<(List<EFClient>, string, string)> GetStatusAsync(IRConConnection connection)
{
var response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS);
_logger.LogDebug("Status Response {response}", string.Join(Environment.NewLine, response));
return new StatusResponse
{
Clients = ClientsFromStatus(response).ToArray(),
Map = GetValueFromStatus<string>(response, ParserRegex.GroupType.RConStatusMap, Configuration.MapStatus.Pattern),
GameType = GetValueFromStatus<string>(response, ParserRegex.GroupType.RConStatusGametype, Configuration.GametypeStatus.Pattern),
Hostname = GetValueFromStatus<string>(response, ParserRegex.GroupType.RConStatusHostname, Configuration.HostnameStatus.Pattern),
MaxClients = GetValueFromStatus<int?>(response, ParserRegex.GroupType.RConStatusMaxPlayers, Configuration.MaxPlayersStatus.Pattern)
};
}
private T GetValueFromStatus<T>(IEnumerable<string> response, ParserRegex.GroupType groupType, string groupPattern)
{
if (string.IsNullOrEmpty(groupPattern))
{
return default;
}
string value = null;
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS);
#if DEBUG
foreach (var line in response)
{
var regex = Regex.Match(line, groupPattern);
Console.WriteLine(line);
}
#endif
return (ClientsFromStatus(response), MapFromStatus(response), GameTypeFromStatus(response));
}
private string MapFromStatus(string[] response)
{
string map = null;
foreach (var line in response)
{
var regex = Regex.Match(line, Configuration.MapStatus.Pattern);
if (regex.Success)
{
value = regex.Groups[Configuration.MapStatus.GroupMapping[groupType]].ToString();
map = regex.Groups[Configuration.MapStatus.GroupMapping[ParserRegex.GroupType.RConStatusMap]].ToString();
}
}
if (value == null)
return map;
}
private string GameTypeFromStatus(string[] response)
{
if (string.IsNullOrWhiteSpace(Configuration.GametypeStatus.Pattern))
{
return default;
return null;
}
if (typeof(T) == typeof(int?))
string gametype = null;
foreach (var line in response)
{
return (T)Convert.ChangeType(int.Parse(value), Nullable.GetUnderlyingType(typeof(T)));
var regex = Regex.Match(line, Configuration.GametypeStatus.Pattern);
if (regex.Success)
{
gametype = regex.Groups[Configuration.GametypeStatus.GroupMapping[ParserRegex.GroupType.RConStatusGametype]].ToString();
}
}
return (T)Convert.ChangeType(value, typeof(T));
return gametype;
}
public async Task<bool> SetDvarAsync(IRConConnection connection, string dvarName, object dvarValue)
{
string dvarString = (dvarValue is string str)
? $"{dvarName} \"{str}\""
: $"{dvarName} {dvarValue}";
: $"{dvarName} {dvarValue.ToString()}";
return (await connection.SendQueryAsync(StaticHelpers.QueryType.SET_DVAR, dvarString)).Length > 0;
}
@ -211,21 +190,10 @@ namespace IW4MAdmin.Application.RConParsers
if (match.Success)
{
if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI")
{
_logger.LogDebug("Ignoring detected client {client} because they are zombie state", string.Join(",", match.Values));
continue;
}
int clientNumber = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConClientNumber]]);
int score = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConScore]]);
var clientNumber = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConClientNumber]]);
var score = 0;
if (Configuration.Status.GroupMapping[ParserRegex.GroupType.RConScore] > 0)
{
score = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConScore]]);
}
var ping = 999;
int ping = 999;
// their state can be CNCT, ZMBI etc
if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]].Length <= 3)
@ -234,15 +202,14 @@ namespace IW4MAdmin.Application.RConParsers
}
long networkId;
var name = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConName]].TrimNewLine();
string name = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConName]].TrimNewLine();
string networkIdString;
var ip = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConIpAddress]].Split(':')[0].ConvertToIP();
try
{
networkIdString = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConNetworkId]];
networkId = networkIdString.IsBotGuid() || (ip == null && ping == 999) ?
networkId = networkIdString.IsBotGuid() ?
name.GenerateGuidFromString() :
networkIdString.ConvertGuidToLong(Configuration.GuidNumberStyle);
}
@ -252,6 +219,8 @@ namespace IW4MAdmin.Application.RConParsers
continue;
}
int? ip = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConIpAddress]].Split(':')[0].ConvertToIP();
var client = new EFClient()
{
CurrentAlias = new EFAlias()
@ -268,17 +237,6 @@ namespace IW4MAdmin.Application.RConParsers
client.SetAdditionalProperty("BotGuid", networkIdString);
if (Configuration.Status.GroupMapping.ContainsKey(ParserRegex.GroupType.AdditionalGroup))
{
var additionalGroupIndex =
Configuration.Status.GroupMapping[ParserRegex.GroupType.AdditionalGroup];
if (match.Values.Length > additionalGroupIndex)
{
client.SetAdditionalProperty("ConnectionClientId", match.Values[additionalGroupIndex]);
}
}
StatusPlayers.Add(client);
}
}
@ -305,16 +263,5 @@ namespace IW4MAdmin.Application.RConParsers
public T GetDefaultDvarValue<T>(string dvarName) => Configuration.DefaultDvarValues.ContainsKey(dvarName) ?
(T)Convert.ChangeType(Configuration.DefaultDvarValues[dvarName], typeof(T)) :
default;
public TimeSpan OverrideTimeoutForCommand(string command)
{
if (command.Contains("map_rotate", StringComparison.InvariantCultureIgnoreCase) ||
command.StartsWith("map ", StringComparison.InvariantCultureIgnoreCase))
{
return TimeSpan.FromSeconds(30);
}
return TimeSpan.Zero;
}
}
}

View File

@ -0,0 +1,15 @@
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.RconParsers
{
/// <summary>
/// empty implementation of the IW4RConParser
/// allows script plugins to generate dynamic RCon parsers
/// </summary>
sealed internal class DynamicRConParser : BaseRConParser
{
public DynamicRConParser(IParserRegexFactory parserRegexFactory) : base(parserRegexFactory)
{
}
}
}

View File

@ -1,10 +1,9 @@
using System;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.RCon;
using System.Collections.Generic;
using System.Globalization;
namespace IW4MAdmin.Application.RConParsers
namespace IW4MAdmin.Application.RconParsers
{
/// <summary>
/// generic implementation of the IRConParserConfiguration
@ -16,8 +15,6 @@ namespace IW4MAdmin.Application.RConParsers
public ParserRegex Status { get; set; }
public ParserRegex MapStatus { get; set; }
public ParserRegex GametypeStatus { get; set; }
public ParserRegex HostnameStatus { get; set; }
public ParserRegex MaxPlayersStatus { get; set; }
public ParserRegex Dvar { get; set; }
public ParserRegex StatusHeader { get; set; }
public string ServerNotRunningResponse { get; set; }
@ -25,9 +22,6 @@ namespace IW4MAdmin.Application.RConParsers
public NumberStyles GuidNumberStyle { get; set; } = NumberStyles.HexNumber;
public IDictionary<string, string> OverrideDvarNameMapping { get; set; } = new Dictionary<string, string>();
public IDictionary<string, string> DefaultDvarValues { get; set; } = new Dictionary<string, string>();
public int NoticeMaximumLines { get; set; } = 8;
public int NoticeMaxCharactersPerLine { get; set; } = 50;
public string NoticeLineSeparator { get; set; } = Environment.NewLine;
public DynamicRConParserConfiguration(IParserRegexFactory parserRegexFactory)
{
@ -36,8 +30,6 @@ namespace IW4MAdmin.Application.RConParsers
GametypeStatus = parserRegexFactory.CreateParserRegex();
Dvar = parserRegexFactory.CreateParserRegex();
StatusHeader = parserRegexFactory.CreateParserRegex();
HostnameStatus = parserRegexFactory.CreateParserRegex();
MaxPlayersStatus = parserRegexFactory.CreateParserRegex();
}
}
}

View File

@ -1,10 +0,0 @@
using System;
namespace Data.Abstractions
{
public class IAuditFields
{
DateTime CreatedDateTime { get; set; }
DateTime? UpdatedDateTime { get; set; }
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace Data.Abstractions
{
public interface IDataValueCache<T, V> where T : class
{
void SetCacheItem(Func<DbSet<T>, CancellationToken, Task<V>> itemGetter, string keyName, TimeSpan? expirationTime = null);
Task<V> GetCacheItem(string keyName, CancellationToken token = default);
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Data.Abstractions
{
public interface ILookupCache<T> where T : class
{
Task InitializeAsync();
Task<T> AddAsync(T item);
Task<T> FirstAsync(Func<T, bool> query);
IEnumerable<T> GetAll();
}
}

View File

@ -1,13 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Data.Abstractions
{
public interface IUniqueId
{
[NotMapped]
long Id { get; }
[NotMapped]
string Value { get; }
}
}

View File

@ -1,148 +0,0 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading;
using System.Threading.Tasks;
using Data.Extensions;
using Data.Models;
using Data.Models.Client;
using Data.Models.Client.Stats;
using Data.Models.Client.Stats.Reference;
using Data.Models.Misc;
using Data.Models.Server;
namespace Data.Context
{
public abstract class DatabaseContext : DbContext
{
public DbSet<EFClient> Clients { get; set; }
public DbSet<EFAlias> Aliases { get; set; }
public DbSet<EFAliasLink> AliasLinks { get; set; }
public DbSet<EFPenalty> Penalties { get; set; }
public DbSet<EFMeta> EFMeta { get; set; }
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
#region STATS
public DbSet<Models.Vector3> Vector3s { get; set; }
public DbSet<EFACSnapshotVector3> SnapshotVector3s { get; set; }
public DbSet<EFACSnapshot> ACSnapshots { get; set; }
public DbSet<EFServer> Servers { get; set; }
public DbSet<EFClientKill> ClientKills { get; set; }
public DbSet<EFClientMessage> ClientMessages { get; set; }
public DbSet<EFServerStatistics> ServerStatistics { get; set; }
public DbSet<EFHitLocation> HitLocations { get; set; }
public DbSet<EFClientHitStatistic> HitStatistics { get; set; }
public DbSet<EFWeapon> Weapons { get; set; }
public DbSet<EFWeaponAttachment> WeaponAttachments { get; set; }
public DbSet<EFMap> Maps { get; set; }
#endregion
#region MISC
public DbSet<EFInboxMessage> InboxMessages { get; set; }
public DbSet<EFServerSnapshot> ServerSnapshots { get;set; }
public DbSet<EFClientConnectionHistory> ConnectionHistory { get; set; }
#endregion
private void SetAuditColumns()
{
return;
}
public DatabaseContext()
{
if (!MigrationExtensions.IsMigration)
{
throw new InvalidOperationException();
}
}
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
{
}
protected DatabaseContext(DbContextOptions options) : base(options)
{
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = default)
{
SetAuditColumns();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
public override int SaveChanges()
{
SetAuditColumns();
return base.SaveChanges();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// make network id unique
modelBuilder.Entity<EFClient>(entity => { entity.HasIndex(e => e.NetworkId).IsUnique(); });
modelBuilder.Entity<EFPenalty>(entity =>
{
entity.HasOne(p => p.Offender)
.WithMany(c => c.ReceivedPenalties)
.HasForeignKey(c => c.OffenderId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasOne(p => p.Punisher)
.WithMany(p => p.AdministeredPenalties)
.HasForeignKey(c => c.PunisherId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(p => p.Expires)
.IsRequired(false);
});
modelBuilder.Entity<EFAliasLink>(entity =>
{
entity.HasMany(e => e.Children)
.WithOne(a => a.Link)
.HasForeignKey(k => k.LinkId)
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<EFAlias>(ent =>
{
ent.Property(a => a.IPAddress).IsRequired(false);
ent.HasIndex(a => a.IPAddress);
ent.Property(a => a.Name).HasMaxLength(24);
ent.HasIndex(a => a.Name);
ent.Property(_alias => _alias.SearchableName).HasMaxLength(24);
ent.HasIndex(_alias => _alias.SearchableName);
ent.HasIndex(_alias => new {_alias.Name, _alias.IPAddress}).IsUnique();
});
modelBuilder.Entity<EFMeta>(ent =>
{
ent.HasIndex(_meta => _meta.Key);
ent.HasIndex(_meta => _meta.LinkedMetaId);
ent.HasOne(_meta => _meta.LinkedMeta)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity<EFClientConnectionHistory>(ent => ent.HasIndex(history => history.CreatedDateTime));
// force full name for database conversion
modelBuilder.Entity<EFClient>().ToTable("EFClients");
modelBuilder.Entity<EFAlias>().ToTable("EFAlias");
modelBuilder.Entity<EFAliasLink>().ToTable("EFAliasLinks");
modelBuilder.Entity<EFPenalty>().ToTable("EFPenalties");
modelBuilder.Entity<EFServerSnapshot>().ToTable(nameof(EFServerSnapshot));
modelBuilder.Entity<EFClientConnectionHistory>().ToTable(nameof(EFClientConnectionHistory));
Models.Configuration.StatsModelConfiguration.Configure(modelBuilder);
base.OnModelCreating(modelBuilder);
}
}
}

View File

@ -1,30 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Configurations>Debug;Release;Prerelease</Configurations>
<Platforms>AnyCPU</Platforms>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>RaidMax.IW4MAdmin.Data</PackageId>
<Title>RaidMax.IW4MAdmin.Data</Title>
<Authors />
<PackageVersion>1.0.7</PackageVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql" Version="4.1.7" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.10" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.10" />
</ItemGroup>
</Project>

View File

@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
namespace Data.Extensions
{
public static class MigrationExtensions
{
public static bool IsMigration => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Migration";
}
}

View File

@ -1,88 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Data.Helpers
{
public class DataValueCache<T, V> : IDataValueCache<T, V> where T : class
{
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
private readonly Dictionary<string, CacheState> _cacheStates = new Dictionary<string, CacheState>();
private const int DefaultExpireMinutes = 15;
private class CacheState
{
public string Key { get; set; }
public DateTime LastRetrieval { get; set; }
public TimeSpan ExpirationTime { get; set; }
public Func<DbSet<T>, CancellationToken, Task<V>> Getter { get; set; }
public V Value { get; set; }
public bool IsExpired => ExpirationTime != TimeSpan.MaxValue &&
(DateTime.Now - LastRetrieval.Add(ExpirationTime)).TotalSeconds > 0;
}
public DataValueCache(ILogger<DataValueCache<T, V>> logger, IDatabaseContextFactory contextFactory)
{
_logger = logger;
_contextFactory = contextFactory;
}
public void SetCacheItem(Func<DbSet<T>, CancellationToken, Task<V>> getter, string key,
TimeSpan? expirationTime = null)
{
if (_cacheStates.ContainsKey(key))
{
_logger.LogDebug("Cache key {key} is already added", key);
return;
}
var state = new CacheState()
{
Key = key,
Getter = getter,
ExpirationTime = expirationTime ?? TimeSpan.FromMinutes(DefaultExpireMinutes)
};
_cacheStates.Add(key, state);
}
public async Task<V> GetCacheItem(string keyName, CancellationToken cancellationToken = default)
{
if (!_cacheStates.ContainsKey(keyName))
{
throw new ArgumentException("No cache found for key {key}", keyName);
}
var state = _cacheStates[keyName];
if (state.IsExpired || state.Value == null)
{
await RunCacheUpdate(state, cancellationToken);
}
return state.Value;
}
private async Task RunCacheUpdate(CacheState state, CancellationToken token)
{
try
{
await using var context = _contextFactory.CreateContext(false);
var set = context.Set<T>();
var value = await state.Getter(set, token);
state.Value = value;
state.LastRetrieval = DateTime.Now;
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not get cached value for {key}", state.Key);
}
}
}
}

View File

@ -1,114 +0,0 @@
using Data.Abstractions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Data.Helpers
{
public class LookupCache<T> : ILookupCache<T> where T : class, IUniqueId
{
private readonly ILogger _logger;
private readonly IDatabaseContextFactory _contextFactory;
private Dictionary<long, T> _cachedItems;
private readonly SemaphoreSlim _onOperation = new SemaphoreSlim(1, 1);
public LookupCache(ILogger<LookupCache<T>> logger, IDatabaseContextFactory contextFactory)
{
_logger = logger;
_contextFactory = contextFactory;
}
public async Task<T> AddAsync(T item)
{
await _onOperation.WaitAsync();
T existingItem = null;
if (_cachedItems.ContainsKey(item.Id))
{
existingItem = _cachedItems[item.Id];
}
if (existingItem != null)
{
_logger.LogDebug("Cached item already added for {type} {id} {value}", typeof(T).Name, item.Id,
item.Value);
_onOperation.Release();
return existingItem;
}
try
{
_logger.LogDebug("Adding new {type} with {id} {value}", typeof(T).Name, item.Id, item.Value);
await using var context = _contextFactory.CreateContext();
context.Set<T>().Add(item);
await context.SaveChangesAsync();
_cachedItems.Add(item.Id, item);
return item;
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not add item to cache for {type}", typeof(T).Name);
throw new Exception("Could not add item to cache");
}
finally
{
if (_onOperation.CurrentCount == 0)
{
_onOperation.Release();
}
}
}
public async Task<T> FirstAsync(Func<T, bool> query)
{
await _onOperation.WaitAsync();
try
{
var cachedResult = _cachedItems.Values.Where(query);
if (cachedResult.Any())
{
return cachedResult.FirstOrDefault();
}
}
catch
{
}
finally
{
if (_onOperation.CurrentCount == 0)
{
_onOperation.Release(1);
}
}
return null;
}
public IEnumerable<T> GetAll()
{
return _cachedItems.Values;
}
public async Task InitializeAsync()
{
try
{
await using var context = _contextFactory.CreateContext();
_cachedItems = await context.Set<T>().ToDictionaryAsync(item => item.Id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not initialize caching for {cacheType}", typeof(T).Name);
}
}
}
}

View File

@ -1,33 +0,0 @@
using System;
using Data.Context;
using Data.Extensions;
using Microsoft.EntityFrameworkCore;
namespace Data.MigrationContext
{
public class MySqlDatabaseContext : DatabaseContext
{
public MySqlDatabaseContext()
{
if (!MigrationExtensions.IsMigration)
{
throw new InvalidOperationException();
}
}
public MySqlDatabaseContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (MigrationExtensions.IsMigration)
{
optionsBuilder.UseMySql("Server=127.0.0.1;Database=IW4MAdmin_Migration;Uid=root;Pwd=password;")
.EnableDetailedErrors(true)
.EnableSensitiveDataLogging(true);
}
}
}
}

View File

@ -1,34 +0,0 @@
using System;
using Data.Context;
using Data.Extensions;
using Microsoft.EntityFrameworkCore;
namespace Data.MigrationContext
{
public class PostgresqlDatabaseContext : DatabaseContext
{
public PostgresqlDatabaseContext()
{
if (!MigrationExtensions.IsMigration)
{
throw new InvalidOperationException();
}
}
public PostgresqlDatabaseContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (MigrationExtensions.IsMigration)
{
optionsBuilder.UseNpgsql(
"Host=127.0.0.1;Database=IW4MAdmin_Migration;Username=postgres;Password=password;",
options => options.SetPostgresVersion(new Version("9.4")))
.EnableDetailedErrors(true)
.EnableSensitiveDataLogging(true);
}
}
}
}

View File

@ -1,33 +0,0 @@
using System;
using Data.Context;
using Data.Extensions;
using Microsoft.EntityFrameworkCore;
namespace Data.MigrationContext
{
public class SqliteDatabaseContext : DatabaseContext
{
public SqliteDatabaseContext()
{
if (!MigrationExtensions.IsMigration)
{
throw new InvalidOperationException();
}
}
public SqliteDatabaseContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (MigrationExtensions.IsMigration)
{
optionsBuilder.UseSqlite("Data Source=IW4MAdmin_Migration.db")
.EnableDetailedErrors(true)
.EnableSensitiveDataLogging(true);
}
}
}
}

View File

@ -1,483 +0,0 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "EFAliasLinks",
columns: table => new
{
AliasLinkId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFAliasLinks", x => x.AliasLinkId);
});
migrationBuilder.CreateTable(
name: "EFServers",
columns: table => new
{
ServerId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
Port = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFServers", x => x.ServerId);
});
migrationBuilder.CreateTable(
name: "Vector3",
columns: table => new
{
Vector3Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
X = table.Column<float>(nullable: false),
Y = table.Column<float>(nullable: false),
Z = table.Column<float>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Vector3", x => x.Vector3Id);
});
migrationBuilder.CreateTable(
name: "EFAlias",
columns: table => new
{
AliasId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: false),
IPAddress = table.Column<int>(nullable: false),
LinkId = table.Column<int>(nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFAlias", x => x.AliasId);
table.ForeignKey(
name: "FK_EFAlias_EFAliasLinks_LinkId",
column: x => x.LinkId,
principalTable: "EFAliasLinks",
principalColumn: "AliasLinkId",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "EFServerStatistics",
columns: table => new
{
StatisticId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ServerId = table.Column<int>(nullable: false),
TotalKills = table.Column<long>(nullable: false),
TotalPlayTime = table.Column<long>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFServerStatistics", x => x.StatisticId);
table.ForeignKey(
name: "FK_EFServerStatistics_EFServers_ServerId",
column: x => x.ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EFClients",
columns: table => new
{
ClientId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
AliasLinkId = table.Column<int>(nullable: false),
Connections = table.Column<int>(nullable: false),
CurrentAliasId = table.Column<int>(nullable: false),
FirstConnection = table.Column<DateTime>(nullable: false),
LastConnection = table.Column<DateTime>(nullable: false),
Level = table.Column<int>(nullable: false),
Masked = table.Column<bool>(nullable: false),
NetworkId = table.Column<long>(nullable: false),
Password = table.Column<string>(nullable: true),
PasswordSalt = table.Column<string>(nullable: true),
TotalConnectionTime = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFClients", x => x.ClientId);
table.ForeignKey(
name: "FK_EFClients_EFAliasLinks_AliasLinkId",
column: x => x.AliasLinkId,
principalTable: "EFAliasLinks",
principalColumn: "AliasLinkId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClients_EFAlias_CurrentAliasId",
column: x => x.CurrentAliasId,
principalTable: "EFAlias",
principalColumn: "AliasId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EFClientKills",
columns: table => new
{
KillId = table.Column<long>(nullable: false)
.Annotation("Sqlite:Autoincrement", true).
Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
AttackerId = table.Column<int>(nullable: false),
Damage = table.Column<int>(nullable: false),
DeathOriginVector3Id = table.Column<int>(nullable: true),
DeathType = table.Column<int>(nullable: false),
HitLoc = table.Column<int>(nullable: false),
KillOriginVector3Id = table.Column<int>(nullable: true),
Map = table.Column<int>(nullable: false),
ServerId = table.Column<int>(nullable: false),
VictimId = table.Column<int>(nullable: false),
ViewAnglesVector3Id = table.Column<int>(nullable: true),
Weapon = table.Column<int>(nullable: false),
When = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFClientKills", x => x.KillId);
table.ForeignKey(
name: "FK_EFClientKills_EFClients_AttackerId",
column: x => x.AttackerId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClientKills_Vector3_DeathOriginVector3Id",
column: x => x.DeathOriginVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFClientKills_Vector3_KillOriginVector3Id",
column: x => x.KillOriginVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFClientKills_EFServers_ServerId",
column: x => x.ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClientKills_EFClients_VictimId",
column: x => x.VictimId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClientKills_Vector3_ViewAnglesVector3Id",
column: x => x.ViewAnglesVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "EFClientMessages",
columns: table => new
{
MessageId = table.Column<long>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ClientId = table.Column<int>(nullable: false),
Message = table.Column<string>(nullable: true),
ServerId = table.Column<int>(nullable: false),
TimeSent = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFClientMessages", x => x.MessageId);
table.ForeignKey(
name: "FK_EFClientMessages_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClientMessages_EFServers_ServerId",
column: x => x.ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EFClientStatistics",
columns: table => new
{
ClientId = table.Column<int>(nullable: false),
ServerId = table.Column<int>(nullable: false),
Active = table.Column<bool>(nullable: false),
Deaths = table.Column<int>(nullable: false),
Kills = table.Column<int>(nullable: false),
SPM = table.Column<double>(nullable: false),
Skill = table.Column<double>(nullable: false),
TimePlayed = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFClientStatistics", x => new { x.ClientId, x.ServerId });
table.ForeignKey(
name: "FK_EFClientStatistics_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFClientStatistics_EFServers_ServerId",
column: x => x.ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EFPenalties",
columns: table => new
{
PenaltyId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
Expires = table.Column<DateTime>(nullable: false),
LinkId = table.Column<int>(nullable: false),
OffenderId = table.Column<int>(nullable: false),
Offense = table.Column<string>(nullable: false),
PunisherId = table.Column<int>(nullable: false),
Type = table.Column<int>(nullable: false),
When = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFPenalties", x => x.PenaltyId);
table.ForeignKey(
name: "FK_EFPenalties_EFAliasLinks_LinkId",
column: x => x.LinkId,
principalTable: "EFAliasLinks",
principalColumn: "AliasLinkId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFPenalties_EFClients_OffenderId",
column: x => x.OffenderId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFPenalties_EFClients_PunisherId",
column: x => x.PunisherId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "EFHitLocationCounts",
columns: table => new
{
HitLocationCountId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true).
Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn).
Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
EFClientStatistics_ClientId = table.Column<int>(nullable: false),
HitCount = table.Column<int>(nullable: false),
HitOffsetAverage = table.Column<float>(nullable: false),
Location = table.Column<int>(nullable: false),
EFClientStatistics_ServerId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFHitLocationCounts", x => x.HitLocationCountId);
table.ForeignKey(
name: "FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId",
column: x => x.EFClientStatistics_ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId",
column: x => x.EFClientStatistics_ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId",
columns: x => new { x.EFClientStatistics_ClientId, x.EFClientStatistics_ServerId },
principalTable: "EFClientStatistics",
principalColumns: new[] { "ClientId", "ServerId" },
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_EFAlias_LinkId",
table: "EFAlias",
column: "LinkId");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_AttackerId",
table: "EFClientKills",
column: "AttackerId");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_DeathOriginVector3Id",
table: "EFClientKills",
column: "DeathOriginVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_KillOriginVector3Id",
table: "EFClientKills",
column: "KillOriginVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_ServerId",
table: "EFClientKills",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_VictimId",
table: "EFClientKills",
column: "VictimId");
migrationBuilder.CreateIndex(
name: "IX_EFClientKills_ViewAnglesVector3Id",
table: "EFClientKills",
column: "ViewAnglesVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFClientMessages_ClientId",
table: "EFClientMessages",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_EFClientMessages_ServerId",
table: "EFClientMessages",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_EFClients_AliasLinkId",
table: "EFClients",
column: "AliasLinkId");
migrationBuilder.CreateIndex(
name: "IX_EFClients_CurrentAliasId",
table: "EFClients",
column: "CurrentAliasId");
migrationBuilder.CreateIndex(
name: "IX_EFClients_NetworkId",
table: "EFClients",
column: "NetworkId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_EFClientStatistics_ServerId",
table: "EFClientStatistics",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_EFHitLocationCounts_EFClientStatistics_ServerId",
table: "EFHitLocationCounts",
column: "EFClientStatistics_ServerId");
migrationBuilder.CreateIndex(
name: "IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId",
table: "EFHitLocationCounts",
columns: new[] { "EFClientStatistics_ClientId", "EFClientStatistics_ServerId" });
migrationBuilder.CreateIndex(
name: "IX_EFPenalties_LinkId",
table: "EFPenalties",
column: "LinkId");
migrationBuilder.CreateIndex(
name: "IX_EFPenalties_OffenderId",
table: "EFPenalties",
column: "OffenderId");
migrationBuilder.CreateIndex(
name: "IX_EFPenalties_PunisherId",
table: "EFPenalties",
column: "PunisherId");
migrationBuilder.CreateIndex(
name: "IX_EFServerStatistics_ServerId",
table: "EFServerStatistics",
column: "ServerId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EFClientKills");
migrationBuilder.DropTable(
name: "EFClientMessages");
migrationBuilder.DropTable(
name: "EFHitLocationCounts");
migrationBuilder.DropTable(
name: "EFPenalties");
migrationBuilder.DropTable(
name: "EFServerStatistics");
migrationBuilder.DropTable(
name: "Vector3");
migrationBuilder.DropTable(
name: "EFClientStatistics");
migrationBuilder.DropTable(
name: "EFClients");
migrationBuilder.DropTable(
name: "EFServers");
migrationBuilder.DropTable(
name: "EFAlias");
migrationBuilder.DropTable(
name: "EFAliasLinks");
}
}
}

View File

@ -1,35 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class Update : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<float>(
name: "MaxAngleDistance",
table: "EFHitLocationCounts",
nullable: false,
defaultValue: 0f);
migrationBuilder.AddColumn<double>(
name: "MaxStrain",
table: "EFClientStatistics",
nullable: false,
defaultValue: 0.0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "MaxAngleDistance",
table: "EFHitLocationCounts");
migrationBuilder.DropColumn(
name: "MaxStrain",
table: "EFClientStatistics");
}
}
}

View File

@ -1,501 +0,0 @@
// <auto-generated />
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 Data.MigrationContext;
using System;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")]
partial class AddAutomatedOffenseAndRatingHistory
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
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<int>("HitLoc");
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<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("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.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.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<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.ToTable("Vector3");
});
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.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);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,101 +0,0 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class AddAutomatedOffenseAndRatingHistory : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "AutomatedOffense",
table: "EFPenalties",
nullable: true);
migrationBuilder.CreateTable(
name: "EFClientRatingHistory",
columns: table => new
{
RatingHistoryId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ClientId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFClientRatingHistory", x => x.RatingHistoryId);
table.ForeignKey(
name: "FK_EFClientRatingHistory_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EFRating",
columns: table => new
{
RatingId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
Newest = table.Column<bool>(nullable: false),
Performance = table.Column<double>(nullable: false),
Ranking = table.Column<int>(nullable: false),
RatingHistoryId = table.Column<int>(nullable: false),
ServerId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_EFRating", x => x.RatingId);
table.ForeignKey(
name: "FK_EFRating_EFClientRatingHistory_RatingHistoryId",
column: x => x.RatingHistoryId,
principalTable: "EFClientRatingHistory",
principalColumn: "RatingHistoryId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFRating_EFServers_ServerId",
column: x => x.ServerId,
principalTable: "EFServers",
principalColumn: "ServerId",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_EFClientRatingHistory_ClientId",
table: "EFClientRatingHistory",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_EFRating_RatingHistoryId",
table: "EFRating",
column: "RatingHistoryId");
migrationBuilder.CreateIndex(
name: "IX_EFRating_ServerId",
table: "EFRating",
column: "ServerId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EFRating");
migrationBuilder.DropTable(
name: "EFClientRatingHistory");
migrationBuilder.DropColumn(
name: "AutomatedOffense",
table: "EFPenalties");
}
}
}

View File

@ -1,503 +0,0 @@
// <auto-generated />
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 Data.MigrationContext;
using System;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180601172317_AddActivityAmount")]
partial class AddActivityAmount
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
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<int>("HitLoc");
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("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.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.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<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.ToTable("Vector3");
});
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.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);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,25 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class AddActivityAmount : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ActivityAmount",
table: "EFRating",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ActivityAmount",
table: "EFRating");
}
}
}

View File

@ -1,52 +0,0 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class AddClientMeta : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "EFMeta",
columns: table => new
{
MetaId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ClientId = table.Column<int>(nullable: false),
Created = table.Column<DateTime>(nullable: false),
Extra = table.Column<string>(nullable: true),
Key = table.Column<string>(nullable: false),
Updated = table.Column<DateTime>(nullable: false),
Value = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFMeta", x => x.MetaId);
table.ForeignKey(
name: "FK_EFMeta_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_EFMeta_ClientId",
table: "EFMeta",
column: "ClientId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EFMeta");
}
}
}

View File

@ -1,638 +0,0 @@
// <auto-generated />
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 Data.MigrationContext;
using System;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180605191706_AddEFACSnapshots")]
partial class AddEFACSnapshots
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.Property<int>("SnapshotId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<int>("CurrentSessionLength");
b.Property<double>("CurrentStrain");
b.Property<int?>("CurrentViewAngleId");
b.Property<int>("Deaths");
b.Property<double>("Distance");
b.Property<double>("EloRating");
b.Property<int?>("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("CurrentViewAngleId");
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<int>("HitLoc");
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("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.EFClient", b =>
{
b.Property<int>("ClientId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AliasLinkId");
b.Property<int>("Connections");
b.Property<int>("CurrentAliasId");
b.Property<DateTime>("FirstConnection");
b.Property<DateTime>("LastConnection");
b.Property<int>("Level");
b.Property<bool>("Masked");
b.Property<long>("NetworkId");
b.Property<string>("Password");
b.Property<string>("PasswordSalt");
b.Property<int>("TotalConnectionTime");
b.HasKey("ClientId");
b.HasIndex("AliasLinkId");
b.HasIndex("CurrentAliasId");
b.HasIndex("NetworkId")
.IsUnique();
b.ToTable("EFClients");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.Property<int>("MetaId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<DateTime>("Created");
b.Property<string>("Extra");
b.Property<string>("Key")
.IsRequired();
b.Property<DateTime>("Updated");
b.Property<string>("Value")
.IsRequired();
b.HasKey("MetaId");
b.HasIndex("ClientId");
b.ToTable("EFMeta");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.Property<int>("PenaltyId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("AutomatedOffense");
b.Property<DateTime>("Expires");
b.Property<int>("LinkId");
b.Property<int>("OffenderId");
b.Property<string>("Offense")
.IsRequired();
b.Property<int>("PunisherId");
b.Property<int>("Type");
b.Property<DateTime>("When");
b.HasKey("PenaltyId");
b.HasIndex("LinkId");
b.HasIndex("OffenderId");
b.HasIndex("PunisherId");
b.ToTable("EFPenalties");
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.Property<int>("Vector3Id")
.ValueGeneratedOnAdd();
b.Property<int?>("EFACSnapshotSnapshotId");
b.Property<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.HasIndex("EFACSnapshotSnapshotId");
b.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId");
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
}
}
}

View File

@ -1,144 +0,0 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using System;
using System.Collections.Generic;
namespace Data.Migrations.MySql
{
public partial class AddEFACSnapshots : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "EFACSnapshotSnapshotId",
table: "Vector3",
nullable: true);
migrationBuilder.CreateTable(
name: "EFACSnapshot",
columns: table => new
{
SnapshotId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ClientId = table.Column<int>(nullable: false),
CurrentSessionLength = table.Column<int>(nullable: false),
CurrentStrain = table.Column<double>(nullable: false),
CurrentViewAngleId = table.Column<int>(nullable: true),
Deaths = table.Column<int>(nullable: false),
Distance = table.Column<double>(nullable: false),
EloRating = table.Column<double>(nullable: false),
HitDestinationVector3Id = table.Column<int>(nullable: true),
HitLocation = table.Column<int>(nullable: false),
HitOriginVector3Id = table.Column<int>(nullable: true),
HitType = table.Column<int>(nullable: false),
Hits = table.Column<int>(nullable: false),
Kills = table.Column<int>(nullable: false),
LastStrainAngleVector3Id = table.Column<int>(nullable: true),
SessionAngleOffset = table.Column<double>(nullable: false),
SessionSPM = table.Column<double>(nullable: false),
SessionScore = table.Column<int>(nullable: false),
StrainAngleBetween = table.Column<double>(nullable: false),
TimeSinceLastEvent = table.Column<int>(nullable: false),
WeaponId = table.Column<int>(nullable: false),
When = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId);
table.ForeignKey(
name: "FK_EFACSnapshot_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId",
column: x => x.CurrentViewAngleId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id",
column: x => x.HitDestinationVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id",
column: x => x.HitOriginVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id",
column: x => x.LastStrainAngleVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Vector3_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_ClientId",
table: "EFACSnapshot",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_CurrentViewAngleId",
table: "EFACSnapshot",
column: "CurrentViewAngleId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitDestinationVector3Id",
table: "EFACSnapshot",
column: "HitDestinationVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitOriginVector3Id",
table: "EFACSnapshot",
column: "HitOriginVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_LastStrainAngleVector3Id",
table: "EFACSnapshot",
column: "LastStrainAngleVector3Id");
if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.AddForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId",
principalTable: "EFACSnapshot",
principalColumn: "SnapshotId",
onDelete: ReferentialAction.Restrict);
}
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3");
migrationBuilder.DropTable(
name: "EFACSnapshot");
migrationBuilder.DropIndex(
name: "IX_Vector3_EFACSnapshotSnapshotId",
table: "Vector3");
migrationBuilder.DropColumn(
name: "EFACSnapshotSnapshotId",
table: "Vector3");
}
}
}

View File

@ -1,638 +0,0 @@
// <auto-generated />
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 Data.MigrationContext;
using System;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180614014303_IndexForEFAlias")]
partial class IndexForEFAlias
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.Property<int>("SnapshotId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<int>("CurrentSessionLength");
b.Property<double>("CurrentStrain");
b.Property<int?>("CurrentViewAngleId");
b.Property<int>("Deaths");
b.Property<double>("Distance");
b.Property<double>("EloRating");
b.Property<int?>("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("CurrentViewAngleId");
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<int>("HitLoc");
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.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.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId");
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
}
}
}

View File

@ -1,665 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[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?>("CurrentViewAngleId");
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("CurrentViewAngleId");
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("CurrentViewAngleId");
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
}
}
}

View File

@ -1,63 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Data.Migrations.MySql
{
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
{
ChangeHistoryId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
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");
}
}
}

View File

@ -1,23 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class AddVisibilityPercentage : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<double>(
name: "VisibilityPercentage",
table: "EFClientKills",
nullable: false,
defaultValue: 0.0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "VisibilityPercentage",
table: "EFClientKills");
}
}
}

View File

@ -1,669 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180908004053_AddWhenToRating")]
partial class AddWhenToRating
{
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?>("CurrentViewAngleId");
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("CurrentViewAngleId");
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<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<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.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<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.Property<DateTime>("When");
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.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId");
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
}
}
}

View File

@ -1,677 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180910221749_AddRatingIndexes")]
partial class AddRatingIndexes
{
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?>("CurrentViewAngleId");
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("CurrentViewAngleId");
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<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<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.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<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.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("Performance");
b.HasIndex("Ranking");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<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("CurrentViewAngleId");
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
}
}
}

View File

@ -1,22 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class AddEFAliasNameIndex : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_EFAlias_Name",
table: "EFAlias",
column: "Name");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_EFAlias_Name",
table: "EFAlias");
}
}
}

View File

@ -1,680 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180911190823_AddEFAliasNameMaxLength24")]
partial class AddEFAliasNameMaxLength24
{
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?>("CurrentViewAngleId");
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("CurrentViewAngleId");
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<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<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.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<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.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("Performance");
b.HasIndex("Ranking");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<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()
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
b.HasIndex("LinkId");
b.HasIndex("Name");
b.ToTable("EFAlias");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
{
b.Property<int>("AliasLinkId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.HasKey("AliasLinkId");
b.ToTable("EFAliasLinks");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
{
b.Property<int>("ChangeHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("Comment")
.HasMaxLength(128);
b.Property<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("CurrentViewAngleId");
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
}
}
}

View File

@ -1,686 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180915163111_AddIndexToMessageTimeSent")]
partial class AddIndexToMessageTimeSent
{
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?>("CurrentViewAngleId");
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("CurrentViewAngleId");
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<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<int>("ServerId");
b.Property<DateTime>("TimeSent");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.HasIndex("ServerId");
b.HasIndex("TimeSent");
b.ToTable("EFClientMessages");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.Property<int>("RatingHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.HasKey("RatingHistoryId");
b.HasIndex("ClientId");
b.ToTable("EFClientRatingHistory");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.Property<int>("ClientId");
b.Property<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.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<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.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("Performance");
b.HasIndex("Ranking");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<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()
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
b.HasIndex("LinkId");
b.HasIndex("Name");
b.ToTable("EFAlias");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
{
b.Property<int>("AliasLinkId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.HasKey("AliasLinkId");
b.ToTable("EFAliasLinks");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
{
b.Property<int>("ChangeHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("Comment")
.HasMaxLength(128);
b.Property<string>("CurrentValue");
b.Property<int>("OriginEntityId");
b.Property<string>("PreviousValue");
b.Property<int>("TargetEntityId");
b.Property<DateTime>("TimeChanged");
b.Property<int>("TypeOfChange");
b.HasKey("ChangeHistoryId");
b.ToTable("EFChangeHistory");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.Property<int>("ClientId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AliasLinkId");
b.Property<int>("Connections");
b.Property<int>("CurrentAliasId");
b.Property<DateTime>("FirstConnection");
b.Property<DateTime>("LastConnection");
b.Property<int>("Level");
b.Property<bool>("Masked");
b.Property<long>("NetworkId");
b.Property<string>("Password");
b.Property<string>("PasswordSalt");
b.Property<int>("TotalConnectionTime");
b.HasKey("ClientId");
b.HasIndex("AliasLinkId");
b.HasIndex("CurrentAliasId");
b.HasIndex("NetworkId")
.IsUnique();
b.ToTable("EFClients");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.Property<int>("MetaId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<DateTime>("Created");
b.Property<string>("Extra");
b.Property<string>("Key")
.IsRequired();
b.Property<DateTime>("Updated");
b.Property<string>("Value")
.IsRequired();
b.HasKey("MetaId");
b.HasIndex("ClientId");
b.ToTable("EFMeta");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.Property<int>("PenaltyId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("AutomatedOffense");
b.Property<DateTime>("Expires");
b.Property<int>("LinkId");
b.Property<int>("OffenderId");
b.Property<string>("Offense")
.IsRequired();
b.Property<int>("PunisherId");
b.Property<int>("Type");
b.Property<DateTime>("When");
b.HasKey("PenaltyId");
b.HasIndex("LinkId");
b.HasIndex("OffenderId");
b.HasIndex("PunisherId");
b.ToTable("EFPenalties");
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.Property<int>("Vector3Id")
.ValueGeneratedOnAdd();
b.Property<int?>("EFACSnapshotSnapshotId");
b.Property<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.HasIndex("EFACSnapshotSnapshotId");
b.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId");
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
}
}
}

View File

@ -1,22 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class AddIndexToMessageTimeSent : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_EFClientMessages_TimeSent",
table: "EFClientMessages",
column: "TimeSent");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_EFClientMessages_TimeSent",
table: "EFClientMessages");
}
}
}

View File

@ -1,587 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Data.MigrationContext;
namespace Data.Migrations.MySql
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180922231310_RemoveACSnapShot")]
partial class RemoveACSnapShot
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
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<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<int>("ServerId");
b.Property<DateTime>("TimeSent");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.HasIndex("ServerId");
b.HasIndex("TimeSent");
b.ToTable("EFClientMessages");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.Property<int>("RatingHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.HasKey("RatingHistoryId");
b.HasIndex("ClientId");
b.ToTable("EFClientRatingHistory");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.Property<int>("ClientId");
b.Property<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.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<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.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("Performance");
b.HasIndex("Ranking");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<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()
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
b.HasIndex("LinkId");
b.HasIndex("Name");
b.ToTable("EFAlias");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
{
b.Property<int>("AliasLinkId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.HasKey("AliasLinkId");
b.ToTable("EFAliasLinks");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
{
b.Property<int>("ChangeHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("Comment")
.HasMaxLength(128);
b.Property<string>("CurrentValue");
b.Property<int>("OriginEntityId");
b.Property<string>("PreviousValue");
b.Property<int>("TargetEntityId");
b.Property<DateTime>("TimeChanged");
b.Property<int>("TypeOfChange");
b.HasKey("ChangeHistoryId");
b.ToTable("EFChangeHistory");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.Property<int>("ClientId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AliasLinkId");
b.Property<int>("Connections");
b.Property<int>("CurrentAliasId");
b.Property<DateTime>("FirstConnection");
b.Property<DateTime>("LastConnection");
b.Property<int>("Level");
b.Property<bool>("Masked");
b.Property<long>("NetworkId");
b.Property<string>("Password");
b.Property<string>("PasswordSalt");
b.Property<int>("TotalConnectionTime");
b.HasKey("ClientId");
b.HasIndex("AliasLinkId");
b.HasIndex("CurrentAliasId");
b.HasIndex("NetworkId")
.IsUnique();
b.ToTable("EFClients");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.Property<int>("MetaId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<DateTime>("Created");
b.Property<string>("Extra");
b.Property<string>("Key")
.IsRequired();
b.Property<DateTime>("Updated");
b.Property<string>("Value")
.IsRequired();
b.HasKey("MetaId");
b.HasIndex("ClientId");
b.ToTable("EFMeta");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.Property<int>("PenaltyId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("AutomatedOffense");
b.Property<DateTime>("Expires");
b.Property<int>("LinkId");
b.Property<int>("OffenderId");
b.Property<string>("Offense")
.IsRequired();
b.Property<int>("PunisherId");
b.Property<int>("Type");
b.Property<DateTime>("When");
b.HasKey("PenaltyId");
b.HasIndex("LinkId");
b.HasIndex("OffenderId");
b.HasIndex("PunisherId");
b.ToTable("EFPenalties");
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.Property<int>("Vector3Id")
.ValueGeneratedOnAdd();
b.Property<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.ToTable("Vector3");
});
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);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,139 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Data.Migrations.MySql
{
public partial class RemoveACSnapShot : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.DropForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3");
migrationBuilder.DropColumn(
name: "EFACSnapshotSnapshotId",
table: "Vector3");
}
migrationBuilder.DropTable(
name: "EFACSnapshot");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "EFACSnapshotSnapshotId",
table: "Vector3",
nullable: true);
migrationBuilder.CreateTable(
name: "EFACSnapshot",
columns: table => new
{
SnapshotId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Active = table.Column<bool>(nullable: false),
ClientId = table.Column<int>(nullable: false),
CurrentSessionLength = table.Column<int>(nullable: false),
CurrentStrain = table.Column<double>(nullable: false),
CurrentViewAngleId = table.Column<int>(nullable: true),
Deaths = table.Column<int>(nullable: false),
Distance = table.Column<double>(nullable: false),
EloRating = table.Column<double>(nullable: false),
HitDestinationVector3Id = table.Column<int>(nullable: true),
HitLocation = table.Column<int>(nullable: false),
HitOriginVector3Id = table.Column<int>(nullable: true),
HitType = table.Column<int>(nullable: false),
Hits = table.Column<int>(nullable: false),
Kills = table.Column<int>(nullable: false),
LastStrainAngleVector3Id = table.Column<int>(nullable: true),
SessionAngleOffset = table.Column<double>(nullable: false),
SessionSPM = table.Column<double>(nullable: false),
SessionScore = table.Column<int>(nullable: false),
StrainAngleBetween = table.Column<double>(nullable: false),
TimeSinceLastEvent = table.Column<int>(nullable: false),
WeaponId = table.Column<int>(nullable: false),
When = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId);
table.ForeignKey(
name: "FK_EFACSnapshot_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId",
column: x => x.CurrentViewAngleId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id",
column: x => x.HitDestinationVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id",
column: x => x.HitOriginVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id",
column: x => x.LastStrainAngleVector3Id,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Vector3_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_ClientId",
table: "EFACSnapshot",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_CurrentViewAngleId",
table: "EFACSnapshot",
column: "CurrentViewAngleId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitDestinationVector3Id",
table: "EFACSnapshot",
column: "HitDestinationVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitOriginVector3Id",
table: "EFACSnapshot",
column: "HitOriginVector3Id");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_LastStrainAngleVector3Id",
table: "EFACSnapshot",
column: "LastStrainAngleVector3Id");
migrationBuilder.AddForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId",
principalTable: "EFACSnapshot",
principalColumn: "SnapshotId",
onDelete: ReferentialAction.Restrict);
}
}
}

View File

@ -1,145 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Data.Migrations.MySql
{
public partial class ReaddACSnapshot : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "EFACSnapshot",
columns: table => new
{
Active = table.Column<bool>(nullable: false),
SnapshotId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ClientId = table.Column<int>(nullable: false),
When = table.Column<DateTime>(nullable: false),
CurrentSessionLength = table.Column<int>(nullable: false),
TimeSinceLastEvent = table.Column<int>(nullable: false),
EloRating = table.Column<double>(nullable: false),
SessionScore = table.Column<int>(nullable: false),
SessionSPM = table.Column<double>(nullable: false),
Hits = table.Column<int>(nullable: false),
Kills = table.Column<int>(nullable: false),
Deaths = table.Column<int>(nullable: false),
CurrentStrain = table.Column<double>(nullable: false),
StrainAngleBetween = table.Column<double>(nullable: false),
SessionAngleOffset = table.Column<double>(nullable: false),
LastStrainAngleId = table.Column<int>(nullable: false),
HitOriginId = table.Column<int>(nullable: false),
HitDestinationId = table.Column<int>(nullable: false),
Distance = table.Column<double>(nullable: false),
CurrentViewAngleId = table.Column<int>(nullable: true),
WeaponId = table.Column<int>(nullable: false),
HitLocation = table.Column<int>(nullable: false),
HitType = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId);
table.ForeignKey(
name: "FK_EFACSnapshot_EFClients_ClientId",
column: x => x.ClientId,
principalTable: "EFClients",
principalColumn: "ClientId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId",
column: x => x.CurrentViewAngleId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitDestinationId",
column: x => x.HitDestinationId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_HitOriginId",
column: x => x.HitOriginId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_EFACSnapshot_Vector3_LastStrainAngleId",
column: x => x.LastStrainAngleId,
principalTable: "Vector3",
principalColumn: "Vector3Id",
onDelete: ReferentialAction.Cascade);
});
if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.AddColumn<int>(
name: "EFACSnapshotSnapshotId",
table: "Vector3",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId",
principalTable: "EFACSnapshot",
principalColumn: "SnapshotId",
onDelete: ReferentialAction.Restrict);
migrationBuilder.CreateIndex(
name: "IX_Vector3_EFACSnapshotSnapshotId",
table: "Vector3",
column: "EFACSnapshotSnapshotId");
}
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_ClientId",
table: "EFACSnapshot",
column: "ClientId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_CurrentViewAngleId",
table: "EFACSnapshot",
column: "CurrentViewAngleId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitDestinationId",
table: "EFACSnapshot",
column: "HitDestinationId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_HitOriginId",
table: "EFACSnapshot",
column: "HitOriginId");
migrationBuilder.CreateIndex(
name: "IX_EFACSnapshot_LastStrainAngleId",
table: "EFACSnapshot",
column: "LastStrainAngleId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId",
table: "Vector3");
migrationBuilder.DropTable(
name: "EFACSnapshot");
migrationBuilder.DropIndex(
name: "IX_Vector3_EFACSnapshotSnapshotId",
table: "Vector3");
migrationBuilder.DropColumn(
name: "EFACSnapshotSnapshotId",
table: "Vector3");
}
}
}

View File

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

View File

@ -1,105 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class MakePenaltyExpirationNullable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.Sql(@"PRAGMA foreign_keys = 0;
CREATE TABLE sqlitestudio_temp_table AS SELECT *
FROM EFPenalties;
DROP TABLE EFPenalties;
CREATE TABLE EFPenalties (
PenaltyId INTEGER NOT NULL
CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT,
Active INTEGER NOT NULL,
Expires TEXT,
LinkId INTEGER NOT NULL,
OffenderId INTEGER NOT NULL,
Offense TEXT NOT NULL,
PunisherId INTEGER NOT NULL,
Type INTEGER NOT NULL,
[When] TEXT NOT NULL,
AutomatedOffense TEXT,
CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY (
LinkId
)
REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE,
CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY (
OffenderId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT,
CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY (
PunisherId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT
);
INSERT INTO EFPenalties (
PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
[When],
AutomatedOffense
)
SELECT PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
""When"",
AutomatedOffense
FROM sqlitestudio_temp_table;
DROP TABLE sqlitestudio_temp_table;
CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties(
""LinkId""
);
CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties(
""OffenderId""
);
CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties(
""PunisherId""
);
PRAGMA foreign_keys = 1; ");
}
else
{
migrationBuilder.AlterColumn<DateTime>(
name: "Expires",
table: "EFPenalties",
nullable: true,
oldClrType: typeof(DateTime));
}
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "Expires",
table: "EFPenalties",
nullable: false,
oldClrType: typeof(DateTime),
oldNullable: true);
}
}
}

View File

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

View File

@ -1,85 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class MakeClientIPNullable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.Sql(@"PRAGMA foreign_keys = 0;
CREATE TABLE sqlitestudio_temp_table AS SELECT *
FROM EFAlias;
DROP TABLE EFAlias;
CREATE TABLE EFAlias (
AliasId INTEGER NOT NULL
CONSTRAINT PK_EFAlias PRIMARY KEY AUTOINCREMENT,
Active INTEGER NOT NULL,
DateAdded TEXT NOT NULL,
IPAddress INTEGER,
LinkId INTEGER NOT NULL,
Name TEXT NOT NULL,
CONSTRAINT FK_EFAlias_EFAliasLinks_LinkId FOREIGN KEY (
LinkId
)
REFERENCES EFAliasLinks (AliasLinkId) ON DELETE RESTRICT
);
INSERT INTO EFAlias (
AliasId,
Active,
DateAdded,
IPAddress,
LinkId,
Name
)
SELECT AliasId,
Active,
DateAdded,
IPAddress,
LinkId,
Name
FROM sqlitestudio_temp_table;
DROP TABLE sqlitestudio_temp_table;
CREATE INDEX IX_EFAlias_LinkId ON EFAlias (
""LinkId""
);
CREATE INDEX IX_EFAlias_IPAddress ON EFAlias(
""IPAddress""
);
CREATE INDEX IX_EFAlias_Name ON EFAlias(
""Name""
);
PRAGMA foreign_keys = 1;
", suppressTransaction:true);
}
else
{
migrationBuilder.AlterColumn<int>(
name: "IPAddress",
table: "EFAlias",
nullable: true,
oldClrType: typeof(int));
}
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "IPAddress",
table: "EFAlias",
nullable: false,
oldClrType: typeof(int),
oldNullable: true);
}
}
}

View File

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

View File

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

View File

@ -1,183 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class AddEvadePenaltyFlag : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.Sql(@"PRAGMA foreign_keys = 0;
CREATE TABLE sqlitestudio_temp_table AS SELECT *
FROM EFPenalties;
DROP TABLE EFPenalties;
CREATE TABLE EFPenalties (
PenaltyId INTEGER NOT NULL
CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT,
Active INTEGER NOT NULL,
Expires TEXT,
LinkId INTEGER NOT NULL,
OffenderId INTEGER NOT NULL,
Offense TEXT NOT NULL,
PunisherId INTEGER NOT NULL,
IsEvadedOffense BOOLEAN NOT NULL
DEFAULT (0),
Type INTEGER NOT NULL,
[When] TEXT NOT NULL,
AutomatedOffense TEXT,
CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY (
LinkId
)
REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE,
CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY (
OffenderId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT,
CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY (
PunisherId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT
);
INSERT INTO EFPenalties (
PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
[When],
AutomatedOffense
)
SELECT PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
""When"",
AutomatedOffense
FROM sqlitestudio_temp_table;
DROP TABLE sqlitestudio_temp_table;
CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties(
""LinkId""
);
CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties(
""OffenderId""
);
CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties(
""PunisherId""
);
PRAGMA foreign_keys = 1;", suppressTransaction: false);
}
else
{
migrationBuilder.AddColumn<bool>(
name: "IsEvadedOffense",
table: "EFPenalties",
nullable: false,
defaultValue: false);
}
}
protected override void Down(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
{
migrationBuilder.Sql(@"PRAGMA foreign_keys = 0;
CREATE TABLE sqlitestudio_temp_table AS SELECT *
FROM EFPenalties;
DROP TABLE EFPenalties;
CREATE TABLE EFPenalties (
PenaltyId INTEGER NOT NULL
CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT,
Active INTEGER NOT NULL,
Expires TEXT,
LinkId INTEGER NOT NULL,
OffenderId INTEGER NOT NULL,
Offense TEXT NOT NULL,
PunisherId INTEGER NOT NULL,
Type INTEGER NOT NULL,
[When] TEXT NOT NULL,
AutomatedOffense TEXT,
CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY (
LinkId
)
REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE,
CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY (
OffenderId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT,
CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY (
PunisherId
)
REFERENCES EFClients (ClientId) ON DELETE RESTRICT
);
INSERT INTO EFPenalties (
PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
[When],
AutomatedOffense
)
SELECT PenaltyId,
Active,
Expires,
LinkId,
OffenderId,
Offense,
PunisherId,
Type,
""When"",
AutomatedOffense
FROM sqlitestudio_temp_table;
DROP TABLE sqlitestudio_temp_table;
CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties(
""LinkId""
);
CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties(
""OffenderId""
);
CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties(
""PunisherId""
);
PRAGMA foreign_keys = 1;", suppressTransaction: false);
}
else
{
migrationBuilder.DropColumn(
name: "IsEvadedOffense",
table: "EFPenalties");
}
}
}
}

View File

@ -1,30 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Data.Migrations.MySql
{
public partial class AddIndexToEFMetaKeyAndClientId : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql")
{
migrationBuilder.Sql("CREATE FULLTEXT INDEX IX_EFMeta_Key ON EFMeta ( `Key` );");
}
else
{
migrationBuilder.CreateIndex(
name: "IX_EFMeta_Key",
table: "EFMeta",
column: "Key");
}
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_EFMeta_Key",
table: "EFMeta");
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More