diff --git a/Config.cs b/Config.cs index 9b30ab2..61e2c29 100644 --- a/Config.cs +++ b/Config.cs @@ -3,7 +3,7 @@ namespace Sessions; -public class CoreConfig : BasePluginConfig +public class SessionsConfig : BasePluginConfig { public override int Version { get; set; } = 1; diff --git a/Globals.cs b/Globals.cs index 0231063..8a5b86e 100644 --- a/Globals.cs +++ b/Globals.cs @@ -1,11 +1,12 @@ +using SessionsLibrary; + namespace Sessions; public partial class Sessions { public override string ModuleName => "Sessions"; - public override string ModuleDescription => "Track player sessions"; public override string ModuleAuthor => "github.com/oscar-wos/Sessions"; - public override string ModuleVersion => "1.2.8"; + public override string ModuleVersion => "1.3.0"; public required IDatabase _database; public readonly Ip _ip = new(); diff --git a/IDatabase.cs b/IDatabase.cs index 47332d1..2a720af 100644 --- a/IDatabase.cs +++ b/IDatabase.cs @@ -1,10 +1,12 @@ using Microsoft.Extensions.Logging; +using SessionsLibrary; namespace Sessions; public interface IDatabase { - string BuildConnectionString(CoreConfig config); + string BuildConnectionString(SessionsConfig config); + Task CreateTablesAsync(); Task GetServerAsync(string serverIp, ushort serverPort); Task GetMapAsync(string mapName); @@ -12,9 +14,8 @@ public interface IDatabase Task GetSessionAsync(int playerId, int serverId, int mapId, string ip); Task GetAliasAsync(int playerId); - void CreateTablesAsync(); - void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds); void UpdateSeen(int playerId); + void UpdateSessions(List playerIds, List sessionIds); void InsertAlias(long sessionId, int playerId, string alias); void InsertMessage(long sessionId, int playerId, MessageType messageType, string message); @@ -30,7 +31,7 @@ public class DatabaseFactory : IDatabaseFactory private readonly IDatabase _database; private readonly ILogger _logger; - public DatabaseFactory(CoreConfig config) + public DatabaseFactory(SessionsConfig config) { CheckConfig(config); @@ -45,17 +46,13 @@ public DatabaseFactory(CoreConfig config) }; } - public IDatabase Database => _database; - - private static void CheckConfig(CoreConfig config) + private static void CheckConfig(SessionsConfig config) { - if (string.IsNullOrWhiteSpace(config.DatabaseType) || - string.IsNullOrWhiteSpace(config.DatabaseHost) || - string.IsNullOrWhiteSpace(config.DatabaseUser) || - string.IsNullOrWhiteSpace(config.DatabaseName) || - config.DatabasePort == 0) - { + if (string.IsNullOrWhiteSpace(config.DatabaseType) || string.IsNullOrWhiteSpace(config.DatabaseHost) + || string.IsNullOrWhiteSpace(config.DatabaseUser) || string.IsNullOrWhiteSpace(config.DatabaseName) + || config.DatabasePort == 0) throw new InvalidOperationException("Database is not set in the configuration file"); - } } + + public IDatabase Database => _database; } \ No newline at end of file diff --git a/IDatabaseQueries.cs b/IDatabaseQueries.cs index a642126..e36035c 100644 --- a/IDatabaseQueries.cs +++ b/IDatabaseQueries.cs @@ -62,36 +62,4 @@ public IEnumerable GetCreateQueries() yield return CreateAliases; yield return CreateMessages; } -} - -public class ServerSQL() -{ - public short Id { get; set; } - - public MapSQL? Map { get; set; } -} - -public class MapSQL() -{ - public short Id { get; set; } -} - -public class PlayerSQL() -{ - public int Id { get; set; } - public DateTime FirstSeen { get; set; } - public DateTime LastSeen { get; set; } - - public SessionSQL? Session { get; set; } -} - -public class SessionSQL() -{ - public long Id { get; set; } -} - -public class AliasSQL -{ - public int Id { get; set; } - public required string Alias { get; set; } } \ No newline at end of file diff --git a/PostgreService.cs b/PostgreService.cs index 4121fea..cfbdd4b 100644 --- a/PostgreService.cs +++ b/PostgreService.cs @@ -1,6 +1,7 @@ using Dapper; using Npgsql; using Microsoft.Extensions.Logging; +using SessionsLibrary; namespace Sessions; @@ -12,12 +13,12 @@ public class PostgreService : IDatabase private readonly string _connectionString; private readonly NpgsqlConnection _connection; - public PostgreService(CoreConfig config, ILogger logger) + public PostgreService(SessionsConfig config, ILogger logger) { _logger = logger; _queries = new PostgreServiceQueries(); _connectionString = BuildConnectionString(config); - + try { _connection = new NpgsqlConnection(_connectionString); @@ -30,7 +31,7 @@ public PostgreService(CoreConfig config, ILogger logger) } } - public string BuildConnectionString(CoreConfig config) + public string BuildConnectionString(SessionsConfig config) { NpgsqlConnectionStringBuilder builder = new() { @@ -45,6 +46,24 @@ public string BuildConnectionString(CoreConfig config) return builder.ConnectionString; } + public async Task CreateTablesAsync() + { + try + { + await using NpgsqlTransaction tx = await _connection.BeginTransactionAsync(); + + foreach (string query in _queries.GetCreateQueries()) + await _connection.ExecuteAsync(query, transaction: tx); + + await tx.CommitAsync(); + } + catch (NpgsqlException ex) + { + _logger.LogError(ex, "Failed to create tables"); + throw; + } + } + public async Task GetServerAsync(string serverIp, ushort serverPort) { short serverPortSigned = (short)(serverPort - 0x8000); @@ -127,25 +146,20 @@ public async Task GetSessionAsync(int playerId, int serverId, int ma } } - public async void CreateTablesAsync() + public async void UpdateSeen(int playerId) { try { - await using NpgsqlTransaction tx = await _connection.BeginTransactionAsync(); - - foreach (string query in _queries.GetCreateQueries()) - await _connection.ExecuteAsync(query, transaction: tx); - - await tx.CommitAsync(); + await _connection.ExecuteAsync(_queries.UpdateSeen, new { PlayerId = playerId }); } catch (NpgsqlException ex) { - _logger.LogError(ex, "Failed to create tables"); + _logger.LogError(ex, "Error while updating seen"); throw; } } - public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) + public async void UpdateSessions(List playerIds, List sessionIds) { await using NpgsqlTransaction tx = await _connection.BeginTransactionAsync(); @@ -156,7 +170,7 @@ public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) foreach (long sessionId in sessionIds) await _connection.ExecuteAsync(_queries.UpdateSession, new { SessionId = sessionId }, transaction: tx); - + await tx.CommitAsync(); } catch (NpgsqlException ex) @@ -167,20 +181,7 @@ public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) } } - public void UpdateSeen(int playerId) - { - try - { - _connection.ExecuteAsync(_queries.UpdateSeen, new { PlayerId = playerId }); - } - catch (NpgsqlException ex) - { - _logger.LogError(ex, "Error while updating seen"); - throw; - } - } - - public void InsertAlias(long sessionId, int playerId, string alias) + public async void InsertAlias(long sessionId, int playerId, string alias) { try { @@ -189,8 +190,8 @@ public void InsertAlias(long sessionId, int playerId, string alias) command.Parameters.AddWithValue("@SessionId", sessionId); command.Parameters.AddWithValue("@PlayerId", playerId); command.Parameters.AddWithValue("@Alias", alias); - - command.ExecuteNonQuery(); + + await command.ExecuteNonQueryAsync(); } catch (NpgsqlException ex) { @@ -199,7 +200,7 @@ public void InsertAlias(long sessionId, int playerId, string alias) } } - public void InsertMessage(long sessionId, int playerId, MessageType messageType, string message) + public async void InsertMessage(long sessionId, int playerId, MessageType messageType, string message) { try { @@ -209,8 +210,8 @@ public void InsertMessage(long sessionId, int playerId, MessageType messageType, command.Parameters.AddWithValue("@PlayerId", playerId); command.Parameters.AddWithValue("@MessageType", (int)messageType); command.Parameters.AddWithValue("@Message", message); - - command.ExecuteNonQuery(); + + await command.ExecuteNonQueryAsync(); } catch (NpgsqlException ex) { @@ -276,9 +277,9 @@ message VARCHAR(512) public override string SelectPlayer => "SELECT id, first_seen, last_seen FROM players WHERE steam_id = @SteamId"; public override string InsertPlayer => "INSERT INTO players (steam_id) VALUES (@SteamId) RETURNING id, first_seen, last_seen"; - public override string InsertSession => "INSERT INTO sessions (player_id, server_id, map_id, ip) VALUES (@PlayerId, @ServerId, @MapId, CAST(@Ip as INET)) RETURNING id"; - public override string UpdateSession => "UPDATE sessions SET end_time = NOW() WHERE id = @SessionId"; public override string UpdateSeen => "UPDATE players SET last_seen = NOW() WHERE id = @PlayerId"; + public override string UpdateSession => "UPDATE sessions SET end_time = NOW() WHERE id = @SessionId"; + public override string InsertSession => "INSERT INTO sessions (player_id, server_id, map_id, ip) VALUES (@PlayerId, @ServerId, @MapId, CAST(@Ip as INET)) RETURNING id"; public override string SelectAlias => "SELECT id, alias FROM aliases WHERE player_id = @PlayerId ORDER BY id DESC LIMIT 1"; public override string InsertAlias => "INSERT INTO aliases (session_id, player_id, alias) VALUES (@SessionId, @PlayerId, @Alias)"; diff --git a/README.md b/README.md index fb1808b..a65a408 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Supports postgre + mysql +Supports postgresql + mysql `counterstrikesharp/configs/plugins/Sessions/Sessions.json` ``` { diff --git a/Sessions.cs b/Sessions.cs index 44aab68..a45ab59 100644 --- a/Sessions.cs +++ b/Sessions.cs @@ -1,28 +1,31 @@ -using System.Text.RegularExpressions; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Timers; +using SessionsLibrary; namespace Sessions; -public partial class Sessions : BasePlugin, IPluginConfig +public partial class Sessions : BasePlugin, IPluginConfig { - public CoreConfig Config { get; set; } = new(); - - public void OnConfigParsed(CoreConfig config) - { - Config = config; + public SessionsConfig Config { get; set; } = new(); + public void OnConfigParsed(SessionsConfig config) + { _database = new DatabaseFactory(config).Database; - _database.CreateTablesAsync(); } public override void Load(bool hotReload) { + Capabilities.RegisterPlayerCapability(Capability_Player, player => new SessionsPlayer(player, this)); + string ip = _ip.GetPublicIp(); ushort port = (ushort)ConVar.Find("hostport")!.GetPrimitiveValue(); - _server = _database!.GetServerAsync(ip, port).GetAwaiter().GetResult(); + + _database.CreateTablesAsync().GetAwaiter().GetResult(); + _server = _database.GetServerAsync(ip, port).GetAwaiter().GetResult(); + _timer = AddTimer(1.0f, Timer_Repeat, TimerFlags.REPEAT); RegisterListener(mapName => _server.Map = _database.GetMapAsync(mapName).GetAwaiter().GetResult() @@ -30,10 +33,13 @@ public override void Load(bool hotReload) RegisterListener((playerSlot, steamId) => { - string playerName = Utilities.GetPlayerFromSlot(playerSlot)!.PlayerName; - + CCSPlayerController? player = Utilities.GetPlayerFromSlot(playerSlot); + + if (!IsValidPlayer(player)) + return; + OnPlayerConnect(playerSlot, steamId.SteamId64, NativeAPI.GetPlayerIpAddress(playerSlot).Split(":")[0]).GetAwaiter().GetResult(); - CheckAlias(playerSlot, playerName).GetAwaiter().GetResult(); + CheckAlias(playerSlot, player!.PlayerName).GetAwaiter().GetResult(); }); RegisterListener(playerSlot => @@ -47,40 +53,30 @@ public override void Load(bool hotReload) RegisterEventHandler((@event, info) => { - CCSPlayerController? playerController = Utilities.GetPlayerFromUserid(@event.Userid); - - if (playerController == null || !playerController.IsValid || playerController.IsBot - || @event.Text == null || !_players.TryGetValue(playerController.Slot, out PlayerSQL? value) || value.Session == null) + CCSPlayerController? player = Utilities.GetPlayerFromUserid(@event.Userid); + + if (!IsValidPlayer(player) || !_players.TryGetValue(player!.Slot, out PlayerSQL? value) || value.Session == null) return HookResult.Continue; MessageType messageType = @event.Teamonly ? MessageType.TeamChat : MessageType.Chat; _database.InsertMessage(value.Session.Id, value.Id, messageType, @event.Text); return HookResult.Continue; - }, HookMode.Pre); + }); - _timer = AddTimer(1.0f, Timer_Repeat, TimerFlags.REPEAT); - if (!hotReload) return; - + _server.Map = _database.GetMapAsync(Server.MapName).GetAwaiter().GetResult(); - Utilities.GetPlayers().Where(player => player.IsValid && !player.IsBot).ToList().ForEach(player => { + foreach (CCSPlayerController player in Utilities.GetPlayers()) + { + if (!IsValidPlayer(player)) + continue; + OnPlayerConnect(player.Slot, player.SteamID, NativeAPI.GetPlayerIpAddress(player.Slot).Split(":")[0]).GetAwaiter().GetResult(); CheckAlias(player.Slot, player.PlayerName).GetAwaiter().GetResult(); - }); - } - - public void Timer_Repeat() - { - List playerControllers = Utilities.GetPlayers(); - - PlayerSQL[] players = playerControllers.Where(player => _players.TryGetValue(player.Slot, out PlayerSQL? p)).Select(player => _players[player.Slot]).ToArray(); - int[] playerIds = players.Select(player => player.Id).ToArray(); - long[] sessionIds = players.Where(player => player.Session != null).Select(player => player.Session!.Id).ToArray(); - - _database.UpdateSessionsBulkAsync(playerIds, sessionIds); + } } public async Task OnPlayerConnect(int playerSlot, ulong steamId, string ip) @@ -91,13 +87,36 @@ public async Task OnPlayerConnect(int playerSlot, ulong steamId, string ip) public async Task CheckAlias(int playerSlot, string alias) { - if (!_players.TryGetValue(playerSlot, out PlayerSQL? player)) + if (!_players.TryGetValue(playerSlot, out PlayerSQL? value) || value.Session == null) return; - - AliasSQL? recentAlias = await _database.GetAliasAsync(player.Id); - //alias = Regex.Replace(alias, @"[\\]x[\dA-F]{2}", string.Empty); + + AliasSQL? recentAlias = await _database.GetAliasAsync(value.Id); if (recentAlias == null || recentAlias.Alias != alias) - _database.InsertAlias(player.Session!.Id, player.Id, alias); + _database.InsertAlias(value.Session.Id, value.Id, alias); + } + + public void Timer_Repeat() + { + List playerIds = []; + List sessionIds = []; + + foreach (CCSPlayerController player in Utilities.GetPlayers()) + { + if (!IsValidPlayer(player) || !_players.TryGetValue(player.Slot, out PlayerSQL? value)) + continue; + + playerIds.Add(value.Id); + + if (value.Session != null) + sessionIds.Add(value.Session.Id); + } + + _database.UpdateSessions(playerIds, sessionIds); + } + + private static bool IsValidPlayer(CCSPlayerController? player) + { + return player != null && player.IsValid && !player.IsBot && !player.IsHLTV; } } \ No newline at end of file diff --git a/Sessions.csproj b/Sessions.csproj index 908a8a7..185f1e9 100644 --- a/Sessions.csproj +++ b/Sessions.csproj @@ -9,7 +9,7 @@ - + @@ -17,7 +17,11 @@ - + + + + False + - + \ No newline at end of file diff --git a/SessionsLibrary.cs b/SessionsLibrary.cs new file mode 100644 index 0000000..7af4b31 --- /dev/null +++ b/SessionsLibrary.cs @@ -0,0 +1,18 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; +using SessionsLibrary; + +namespace Sessions; + +public partial class Sessions +{ + public static PlayerCapability Capability_Player { get; } = new("sessions:player"); +} + +public class SessionsPlayer(CCSPlayerController player, Sessions plugin) : ISessionsPlayer +{ + private readonly PlayerSQL? _player = plugin._players.TryGetValue(player.Slot, out PlayerSQL? value) ? value : null; + + public PlayerSQL? PlayerSQL => _player; + public SessionSQL? SessionSQL => _player?.Session; +} \ No newline at end of file diff --git a/SessionsLibrary/ISessions.cs b/SessionsLibrary/ISessions.cs new file mode 100644 index 0000000..346e928 --- /dev/null +++ b/SessionsLibrary/ISessions.cs @@ -0,0 +1,39 @@ +namespace SessionsLibrary; + +public interface ISessionsPlayer +{ + PlayerSQL? PlayerSQL { get; } + SessionSQL? SessionSQL { get; } +} + +public class ServerSQL +{ + public short Id { get; set; } + + public MapSQL? Map { get; set; } +} + +public class MapSQL +{ + public short Id { get; set; } +} + +public class PlayerSQL +{ + public int Id { get; set; } + public DateTime FirstSeen { get; set; } + public DateTime LastSeen { get; set; } + + public SessionSQL? Session { get; set; } +} + +public class SessionSQL +{ + public long Id { get; set; } +} + +public class AliasSQL +{ + public int Id { get; set; } + public required string Alias { get; set; } +} diff --git a/SessionsLibrary/SessionsLibrary.csproj b/SessionsLibrary/SessionsLibrary.csproj new file mode 100644 index 0000000..192a64c --- /dev/null +++ b/SessionsLibrary/SessionsLibrary.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + true + + + + + + + \ No newline at end of file diff --git a/SessionsLibrary/SessionsLibrary.deps.json b/SessionsLibrary/SessionsLibrary.deps.json new file mode 100644 index 0000000..7dc1afd --- /dev/null +++ b/SessionsLibrary/SessionsLibrary.deps.json @@ -0,0 +1,623 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "SessionsLibrary/1.0.0": { + "dependencies": { + "CounterStrikeSharp.API": "1.0.235" + }, + "runtime": { + "SessionsLibrary.dll": {} + } + }, + "CounterStrikeSharp.API/1.0.235": { + "dependencies": { + "McMaster.NETCore.Plugins": "1.4.0", + "Microsoft.CSharp": "4.7.0", + "Microsoft.DotNet.ApiCompat.Task": "8.0.203", + "Microsoft.Extensions.Hosting": "8.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", + "Microsoft.Extensions.Localization.Abstractions": "8.0.3", + "Microsoft.Extensions.Logging": "8.0.0", + "Scrutor": "4.2.2", + "Serilog.Extensions.Logging": "8.0.0", + "Serilog.Sinks.Console": "5.0.0", + "Serilog.Sinks.File": "5.0.0", + "System.Data.DataSetExtensions": "4.5.0" + } + }, + "McMaster.NETCore.Plugins/1.4.0": { + "dependencies": { + "Microsoft.DotNet.PlatformAbstractions": "3.1.6", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.CSharp/4.7.0": {}, + "Microsoft.DotNet.ApiCompat.Task/8.0.203": {}, + "Microsoft.DotNet.PlatformAbstractions/3.1.6": {}, + "Microsoft.Extensions.Configuration/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.CommandLine/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": {}, + "Microsoft.Extensions.DependencyModel/6.0.0": { + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.Diagnostics/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "System.Diagnostics.DiagnosticSource": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical/8.0.0": { + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing/8.0.0": {}, + "Microsoft.Extensions.Hosting/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "8.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", + "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "8.0.0", + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Diagnostics": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Configuration": "8.0.0", + "Microsoft.Extensions.Logging.Console": "8.0.0", + "Microsoft.Extensions.Logging.Debug": "8.0.0", + "Microsoft.Extensions.Logging.EventLog": "8.0.0", + "Microsoft.Extensions.Logging.EventSource": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Hosting.Abstractions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Localization.Abstractions/8.0.3": {}, + "Microsoft.Extensions.Logging/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Configuration/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Console/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Configuration": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Debug/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.EventLog/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "System.Diagnostics.EventLog": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.EventSource/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0", + "System.Text.Json": "8.0.0" + } + }, + "Microsoft.Extensions.Options/8.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives/8.0.0": {}, + "Scrutor/4.2.2": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Serilog/3.1.1": {}, + "Serilog.Extensions.Logging/8.0.0": { + "dependencies": { + "Microsoft.Extensions.Logging": "8.0.0", + "Serilog": "3.1.1" + } + }, + "Serilog.Sinks.Console/5.0.0": { + "dependencies": { + "Serilog": "3.1.1" + } + }, + "Serilog.Sinks.File/5.0.0": { + "dependencies": { + "Serilog": "3.1.1" + } + }, + "System.Buffers/4.5.1": {}, + "System.Data.DataSetExtensions/4.5.0": {}, + "System.Diagnostics.DiagnosticSource/8.0.0": {}, + "System.Diagnostics.EventLog/8.0.0": {}, + "System.Memory/4.5.4": {}, + "System.Runtime.CompilerServices.Unsafe/6.0.0": {}, + "System.Text.Encodings.Web/8.0.0": {}, + "System.Text.Json/8.0.0": { + "dependencies": { + "System.Text.Encodings.Web": "8.0.0" + } + } + } + }, + "libraries": { + "SessionsLibrary/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "CounterStrikeSharp.API/1.0.235": { + "type": "package", + "serviceable": true, + "sha512": "sha512-xBtqRkvNhSdQSbpytT6ROwGBKNurIOV0Ua2e4upEQxBuvksnZqM8j8nsSHIz2NAJ3GD+AIDBg0s3JZ6nlDSGvQ==", + "path": "counterstrikesharp.api/1.0.235", + "hashPath": "counterstrikesharp.api.1.0.235.nupkg.sha512" + }, + "McMaster.NETCore.Plugins/1.4.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UKw5Z2/QHhkR7kiAJmqdCwVDMQV0lwsfj10+FG676r8DsJWIpxtachtEjE0qBs9WoK5GUQIqxgyFeYUSwuPszg==", + "path": "mcmaster.netcore.plugins/1.4.0", + "hashPath": "mcmaster.netcore.plugins.1.4.0.nupkg.sha512" + }, + "Microsoft.CSharp/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==", + "path": "microsoft.csharp/4.7.0", + "hashPath": "microsoft.csharp.4.7.0.nupkg.sha512" + }, + "Microsoft.DotNet.ApiCompat.Task/8.0.203": { + "type": "package", + "serviceable": true, + "sha512": "sha512-nPEGMojf1mj1oVixe0aiBimSn6xUoZswSjpMPZFMkZ+znYm2GEM5tWGZEWb6OSNIo5gWKyDi1WcI4IL7YiL1Zw==", + "path": "microsoft.dotnet.apicompat.task/8.0.203", + "hashPath": "microsoft.dotnet.apicompat.task.8.0.203.nupkg.sha512" + }, + "Microsoft.DotNet.PlatformAbstractions/3.1.6": { + "type": "package", + "serviceable": true, + "sha512": "sha512-jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg==", + "path": "microsoft.dotnet.platformabstractions/3.1.6", + "hashPath": "microsoft.dotnet.platformabstractions.3.1.6.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "path": "microsoft.extensions.configuration/8.0.0", + "hashPath": "microsoft.extensions.configuration.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "path": "microsoft.extensions.configuration.abstractions/8.0.0", + "hashPath": "microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Binder/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-mBMoXLsr5s1y2zOHWmKsE9veDcx8h1x/c3rz4baEdQKTeDcmQAPNbB54Pi/lhFO3K431eEq6PFbMgLaa6PHFfA==", + "path": "microsoft.extensions.configuration.binder/8.0.0", + "hashPath": "microsoft.extensions.configuration.binder.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.CommandLine/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NZuZMz3Q8Z780nKX3ifV1fE7lS+6pynDHK71OfU4OZ1ItgvDOhyOC7E6z+JMZrAj63zRpwbdldYFk499t3+1dQ==", + "path": "microsoft.extensions.configuration.commandline/8.0.0", + "hashPath": "microsoft.extensions.configuration.commandline.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-plvZ0ZIpq+97gdPNNvhwvrEZ92kNml9hd1pe3idMA7svR0PztdzVLkoWLcRFgySYXUJc3kSM3Xw3mNFMo/bxRA==", + "path": "microsoft.extensions.configuration.environmentvariables/8.0.0", + "hashPath": "microsoft.extensions.configuration.environmentvariables.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.FileExtensions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "path": "microsoft.extensions.configuration.fileextensions/8.0.0", + "hashPath": "microsoft.extensions.configuration.fileextensions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Json/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "path": "microsoft.extensions.configuration.json/8.0.0", + "hashPath": "microsoft.extensions.configuration.json.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.UserSecrets/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ihDHu2dJYQird9pl2CbdwuNDfvCZdOS0S7SPlNfhPt0B81UTT+yyZKz2pimFZGUp3AfuBRnqUCxB2SjsZKHVUw==", + "path": "microsoft.extensions.configuration.usersecrets/8.0.0", + "hashPath": "microsoft.extensions.configuration.usersecrets.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "path": "microsoft.extensions.dependencyinjection/8.0.0", + "hashPath": "microsoft.extensions.dependencyinjection.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==", + "path": "microsoft.extensions.dependencyinjection.abstractions/8.0.0", + "hashPath": "microsoft.extensions.dependencyinjection.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyModel/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "path": "microsoft.extensions.dependencymodel/6.0.0", + "hashPath": "microsoft.extensions.dependencymodel.6.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Diagnostics/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3PZp/YSkIXrF7QK7PfC1bkyRYwqOHpWFad8Qx+4wkuumAeXo1NHaxpS9LboNA9OvNSAu+QOVlXbMyoY+pHSqcw==", + "path": "microsoft.extensions.diagnostics/8.0.0", + "hashPath": "microsoft.extensions.diagnostics.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Diagnostics.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", + "path": "microsoft.extensions.diagnostics.abstractions/8.0.0", + "hashPath": "microsoft.extensions.diagnostics.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.FileProviders.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "path": "microsoft.extensions.fileproviders.abstractions/8.0.0", + "hashPath": "microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.FileProviders.Physical/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "path": "microsoft.extensions.fileproviders.physical/8.0.0", + "hashPath": "microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.FileSystemGlobbing/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==", + "path": "microsoft.extensions.filesystemglobbing/8.0.0", + "hashPath": "microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Hosting/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ItYHpdqVp5/oFLT5QqbopnkKlyFG9EW/9nhM6/yfObeKt6Su0wkBio6AizgRHGNwhJuAtlE5VIjow5JOTrip6w==", + "path": "microsoft.extensions.hosting/8.0.0", + "hashPath": "microsoft.extensions.hosting.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Hosting.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-AG7HWwVRdCHlaA++1oKDxLsXIBxmDpMPb3VoyOoAghEWnkUvEAdYQUwnV4jJbAaa/nMYNiEh5ByoLauZBEiovg==", + "path": "microsoft.extensions.hosting.abstractions/8.0.0", + "hashPath": "microsoft.extensions.hosting.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Localization.Abstractions/8.0.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-k/kUPm1FQBxcs9/vsM1eF4qIOg2Sovqh/+KUGHur5Mc0Y3OFGuoz9ktBX7LA0gPz53SZhW3W3oaSaMFFcjgM6Q==", + "path": "microsoft.extensions.localization.abstractions/8.0.3", + "hashPath": "microsoft.extensions.localization.abstractions.8.0.3.nupkg.sha512" + }, + "Microsoft.Extensions.Logging/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "path": "microsoft.extensions.logging/8.0.0", + "hashPath": "microsoft.extensions.logging.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Abstractions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "path": "microsoft.extensions.logging.abstractions/8.0.0", + "hashPath": "microsoft.extensions.logging.abstractions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Configuration/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ixXXV0G/12g6MXK65TLngYN9V5hQQRuV+fZi882WIoVJT7h5JvoYoxTEwCgdqwLjSneqh1O+66gM8sMr9z/rsQ==", + "path": "microsoft.extensions.logging.configuration/8.0.0", + "hashPath": "microsoft.extensions.logging.configuration.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Console/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-e+48o7DztoYog+PY430lPxrM4mm3PbA6qucvQtUDDwVo4MO+ejMw7YGc/o2rnxbxj4isPxdfKFzTxvXMwAz83A==", + "path": "microsoft.extensions.logging.console/8.0.0", + "hashPath": "microsoft.extensions.logging.console.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Debug/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dt0x21qBdudHLW/bjMJpkixv858RRr8eSomgVbU8qljOyfrfDGi1JQvpF9w8S7ziRPtRKisuWaOwFxJM82GxeA==", + "path": "microsoft.extensions.logging.debug/8.0.0", + "hashPath": "microsoft.extensions.logging.debug.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.EventLog/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3X9D3sl7EmOu7vQp5MJrmIJBl5XSdOhZPYXUeFfYa6Nnm9+tok8x3t3IVPLhm7UJtPOU61ohFchw8rNm9tIYOQ==", + "path": "microsoft.extensions.logging.eventlog/8.0.0", + "hashPath": "microsoft.extensions.logging.eventlog.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.EventSource/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-oKcPMrw+luz2DUAKhwFXrmFikZWnyc8l2RKoQwqU3KIZZjcfoJE0zRHAnqATfhRZhtcbjl/QkiY2Xjxp0xu+6w==", + "path": "microsoft.extensions.logging.eventsource/8.0.0", + "hashPath": "microsoft.extensions.logging.eventsource.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Options/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", + "path": "microsoft.extensions.options/8.0.0", + "hashPath": "microsoft.extensions.options.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", + "path": "microsoft.extensions.options.configurationextensions/8.0.0", + "hashPath": "microsoft.extensions.options.configurationextensions.8.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Primitives/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==", + "path": "microsoft.extensions.primitives/8.0.0", + "hashPath": "microsoft.extensions.primitives.8.0.0.nupkg.sha512" + }, + "Scrutor/4.2.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t5VIYA7WJXoJJo7s4DoHakMGwTu+MeEnZumMOhTCH7kz9xWha24G7dJNxWrHPlu0ZdZAS4jDZCxxAnyaBh7uYw==", + "path": "scrutor/4.2.2", + "hashPath": "scrutor.4.2.2.nupkg.sha512" + }, + "Serilog/3.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-P6G4/4Kt9bT635bhuwdXlJ2SCqqn2nhh4gqFqQueCOr9bK/e7W9ll/IoX1Ter948cV2Z/5+5v8pAfJYUISY03A==", + "path": "serilog/3.1.1", + "hashPath": "serilog.3.1.1.nupkg.sha512" + }, + "Serilog.Extensions.Logging/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YEAMWu1UnWgf1c1KP85l1SgXGfiVo0Rz6x08pCiPOIBt2Qe18tcZLvdBUuV5o1QHvrs8FAry9wTIhgBRtjIlEg==", + "path": "serilog.extensions.logging/8.0.0", + "hashPath": "serilog.extensions.logging.8.0.0.nupkg.sha512" + }, + "Serilog.Sinks.Console/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-IZ6bn79k+3SRXOBpwSOClUHikSkp2toGPCZ0teUkscv4dpDg9E2R2xVsNkLmwddE4OpNVO3N0xiYsAH556vN8Q==", + "path": "serilog.sinks.console/5.0.0", + "hashPath": "serilog.sinks.console.5.0.0.nupkg.sha512" + }, + "Serilog.Sinks.File/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "path": "serilog.sinks.file/5.0.0", + "hashPath": "serilog.sinks.file.5.0.0.nupkg.sha512" + }, + "System.Buffers/4.5.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==", + "path": "system.buffers/4.5.1", + "hashPath": "system.buffers.4.5.1.nupkg.sha512" + }, + "System.Data.DataSetExtensions/4.5.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-221clPs1445HkTBZPL+K9sDBdJRB8UN8rgjO3ztB0CQ26z//fmJXtlsr6whGatscsKGBrhJl5bwJuKSA8mwFOw==", + "path": "system.data.datasetextensions/4.5.0", + "hashPath": "system.data.datasetextensions.4.5.0.nupkg.sha512" + }, + "System.Diagnostics.DiagnosticSource/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ==", + "path": "system.diagnostics.diagnosticsource/8.0.0", + "hashPath": "system.diagnostics.diagnosticsource.8.0.0.nupkg.sha512" + }, + "System.Diagnostics.EventLog/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==", + "path": "system.diagnostics.eventlog/8.0.0", + "hashPath": "system.diagnostics.eventlog.8.0.0.nupkg.sha512" + }, + "System.Memory/4.5.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "path": "system.memory/4.5.4", + "hashPath": "system.memory.4.5.4.nupkg.sha512" + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512" + }, + "System.Text.Encodings.Web/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==", + "path": "system.text.encodings.web/8.0.0", + "hashPath": "system.text.encodings.web.8.0.0.nupkg.sha512" + }, + "System.Text.Json/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "path": "system.text.json/8.0.0", + "hashPath": "system.text.json.8.0.0.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/SessionsLibrary/SessionsLibrary.dll b/SessionsLibrary/SessionsLibrary.dll new file mode 100644 index 0000000..4921252 Binary files /dev/null and b/SessionsLibrary/SessionsLibrary.dll differ diff --git a/SessionsLibrary/SessionsLibrary.pdb b/SessionsLibrary/SessionsLibrary.pdb new file mode 100644 index 0000000..d194042 Binary files /dev/null and b/SessionsLibrary/SessionsLibrary.pdb differ diff --git a/SqlService.cs b/SqlService.cs index 32329ba..62b9c50 100644 --- a/SqlService.cs +++ b/SqlService.cs @@ -1,6 +1,7 @@ using Dapper; using MySqlConnector; using Microsoft.Extensions.Logging; +using SessionsLibrary; namespace Sessions; @@ -12,7 +13,7 @@ public class SqlService : IDatabase private readonly string _connectionString; private readonly MySqlConnection _connection; - public SqlService(CoreConfig config, ILogger logger) + public SqlService(SessionsConfig config, ILogger logger) { _logger = logger; _queries = new SqlServiceQueries(); @@ -30,7 +31,7 @@ public SqlService(CoreConfig config, ILogger logger) } } - public string BuildConnectionString(CoreConfig config) + public string BuildConnectionString(SessionsConfig config) { MySqlConnectionStringBuilder builder = new() { @@ -46,6 +47,24 @@ public string BuildConnectionString(CoreConfig config) return builder.ConnectionString; } + public async Task CreateTablesAsync() + { + try + { + await using MySqlTransaction tx = await _connection.BeginTransactionAsync(); + + foreach (string query in _queries.GetCreateQueries()) + await _connection.ExecuteAsync(query, transaction: tx); + + await tx.CommitAsync(); + } + catch (MySqlException ex) + { + _logger.LogError(ex, "Failed to create tables"); + throw; + } + } + public async Task GetServerAsync(string serverIp, ushort serverPort) { try @@ -130,25 +149,19 @@ public async Task GetSessionAsync(int playerId, int serverId, int ma } } - public async void CreateTablesAsync() - { + public async void UpdateSeen(int playerId) { try { - await using MySqlTransaction tx = await _connection.BeginTransactionAsync(); - - foreach (string query in _queries.GetCreateQueries()) - await _connection.ExecuteAsync(query, transaction: tx); - - await tx.CommitAsync(); + await _connection.ExecuteAsync(_queries.UpdateSeen, new { PlayerId = playerId }); } catch (MySqlException ex) { - _logger.LogError(ex, "Failed to create tables"); + _logger.LogError(ex, "Error while updating seen"); throw; } } - public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) + public async void UpdateSessions(List playerIds, List sessionIds) { await using MySqlTransaction tx = await _connection.BeginTransactionAsync(); @@ -159,7 +172,7 @@ public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) foreach (long sessionId in sessionIds) await _connection.ExecuteAsync(_queries.UpdateSession, new { SessionId = sessionId }, transaction: tx); - + await tx.CommitAsync(); } catch (MySqlException ex) @@ -170,19 +183,7 @@ public async void UpdateSessionsBulkAsync(int[] playerIds, long[] sessionIds) } } - public void UpdateSeen(int playerId) { - try - { - _connection.Execute(_queries.UpdateSeen, new { PlayerId = playerId }); - } - catch (MySqlException ex) - { - _logger.LogError(ex, "Error while updating seen"); - throw; - } - } - - public void InsertAlias(long sessionId, int playerId, string alias) + public async void InsertAlias(long sessionId, int playerId, string alias) { try { @@ -191,8 +192,8 @@ public void InsertAlias(long sessionId, int playerId, string alias) command.Parameters.AddWithValue("@SessionId", sessionId); command.Parameters.AddWithValue("@PlayerId", playerId); command.Parameters.AddWithValue("@Alias", alias); - - command.ExecuteNonQuery(); + + await command.ExecuteNonQueryAsync(); } catch (MySqlException ex) { @@ -201,7 +202,7 @@ public void InsertAlias(long sessionId, int playerId, string alias) } } - public void InsertMessage(long sessionId, int playerId, MessageType messageType, string message) + public async void InsertMessage(long sessionId, int playerId, MessageType messageType, string message) { try { @@ -212,7 +213,7 @@ public void InsertMessage(long sessionId, int playerId, MessageType messageType, command.Parameters.AddWithValue("@MessageType", (int)messageType); command.Parameters.AddWithValue("@Message", message); - command.ExecuteNonQuery(); + await command.ExecuteNonQueryAsync(); } catch (MySqlException ex) { @@ -278,9 +279,9 @@ message VARCHAR(128) COLLATE utf8_unicode_520_ci public override string SelectPlayer => "SELECT id FROM players WHERE steam_id = @SteamId"; public override string InsertPlayer => "INSERT INTO players (steam_id) VALUES (@SteamId)"; - public override string InsertSession => "INSERT INTO sessions (player_id, server_id, map_id, ip) VALUES (@PlayerId, @ServerId, @MapId, @Ip); SELECT last_insert_id()"; - public override string UpdateSession => "UPDATE sessions SET end_time = NOW() WHERE id = @SessionId"; public override string UpdateSeen => "UPDATE players SET last_seen = NOW() WHERE id = @PlayerId"; + public override string UpdateSession => "UPDATE sessions SET end_time = NOW() WHERE id = @SessionId"; + public override string InsertSession => "INSERT INTO sessions (player_id, server_id, map_id, ip) VALUES (@PlayerId, @ServerId, @MapId, @Ip); SELECT last_insert_id()"; public override string SelectAlias => "SELECT id, alias FROM aliases WHERE player_id = @PlayerId ORDER BY id DESC LIMIT 1"; public override string InsertAlias => "INSERT INTO aliases (session_id, player_id, alias) VALUES (@SessionId, @PlayerId, @Alias)"; diff --git a/TestPlugin/TestPlugin.cs b/TestPlugin/TestPlugin.cs new file mode 100644 index 0000000..8edb3e0 --- /dev/null +++ b/TestPlugin/TestPlugin.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; +using SessionsLibrary; + +namespace TestPlugin; + +public class TestPlugin : BasePlugin +{ + public override string ModuleName => "TestPlugin"; + public override string ModuleVersion => "1.0.0"; + + public static PlayerCapability Capability_Player { get; } = new("sessions:player"); + + public override void Load(bool isReload) + { + foreach (CCSPlayerController player in Utilities.GetPlayers()) + { + var temp = Capability_Player.Get(player); + var temp2 = temp.SessionSQL; + + Console.WriteLine(temp2.Id); + } + } +} \ No newline at end of file diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj new file mode 100644 index 0000000..4c2100e --- /dev/null +++ b/TestPlugin/TestPlugin.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + ..\SessionsLibrary\obj\Debug\net8.0\SessionsLibrary.dll + False + + + + \ No newline at end of file