Compare commits

..

5 Commits

Author SHA1 Message Date
Eduardo Leonardo
5325caa970 Merge 76bcb5bb85 into 10a4691429 2025-10-20 15:57:54 +00:00
Eduardo Leonardo Rosa da Silva
76bcb5bb85 feat: Add SQLite database support with MySQL compatibility 2025-10-20 12:55:20 -03:00
Dawid Bepierszcz
10a4691429 Merge pull request #456 from daffyyyy/main
Recompile, small change in ontick
2025-10-18 00:57:08 +02:00
Dawid Bepierszcz
ae8fb3b677 Recompile, small change in ontick 2025-10-18 00:55:05 +02:00
Dawid Bepierszcz
1ef12ed6b2 Update WeaponAction.cs 2025-09-18 12:16:29 +02:00
14 changed files with 522 additions and 190 deletions

View File

@@ -91,6 +91,12 @@ namespace WeaponPaints
[JsonPropertyName("DatabaseName")] [JsonPropertyName("DatabaseName")]
public string DatabaseName { get; set; } = ""; public string DatabaseName { get; set; } = "";
[JsonPropertyName("DatabaseType")]
public string DatabaseType { get; set; } = "mysql";
[JsonPropertyName("DatabasePath")]
public string DatabasePath { get; set; } = "weaponpaints.db";
[JsonPropertyName("CmdRefreshCooldownSeconds")] [JsonPropertyName("CmdRefreshCooldownSeconds")]
public int CmdRefreshCooldownSeconds { get; set; } = 3; public int CmdRefreshCooldownSeconds { get; set; } = 3;

View File

@@ -1,23 +1,20 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MySqlConnector;
namespace WeaponPaints namespace WeaponPaints
{ {
public class Database(string dbConnectionString) public class Database
{ {
public async Task<MySqlConnection> GetConnectionAsync() private readonly IDatabaseConnection _connection;
public Database(IDatabaseConnection connection)
{ {
try _connection = connection;
{ }
var connection = new MySqlConnection(dbConnectionString);
await connection.OpenAsync(); public async Task<IDatabaseConnection> GetConnectionAsync()
return connection; {
} await _connection.OpenAsync();
catch (Exception ex) return _connection;
{
WeaponPaints.Instance.Logger.LogError($"Unable to connect to database: {ex.Message}");
throw;
}
} }
} }
} }

View File

@@ -59,6 +59,8 @@ namespace WeaponPaints
catch catch
{ {
} }
Players.Add(player);
return HookResult.Continue; return HookResult.Continue;
} }
@@ -114,6 +116,7 @@ namespace WeaponPaints
_temporaryPlayerWeaponWear.TryRemove(player.Slot, out _); _temporaryPlayerWeaponWear.TryRemove(player.Slot, out _);
CommandsCooldown.Remove(player.Slot); CommandsCooldown.Remove(player.Slot);
Players.Remove(player);
return HookResult.Continue; return HookResult.Continue;
} }
@@ -239,7 +242,7 @@ namespace WeaponPaints
if (steamid != null && steamid.IsValid()) if (steamid != null && steamid.IsValid())
{ {
player = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.SteamID == steamid.SteamId64); player = Players.FirstOrDefault(p => p.IsValid && p.SteamID == steamid.SteamId64);
if (player == null) if (player == null)
player = Utilities.GetPlayerFromSteamId(weapon.OriginalOwnerXuidLow); player = Utilities.GetPlayerFromSteamId(weapon.OriginalOwnerXuidLow);
@@ -266,11 +269,7 @@ namespace WeaponPaints
{ {
if (!Config.Additional.ShowSkinImage) return; if (!Config.Additional.ShowSkinImage) return;
foreach (var player in Utilities.GetPlayers().Where(p => foreach (var player in Players)
p is { IsValid: true, PlayerPawn.IsValid: true, IsBot: false } and
{ Connected: PlayerConnectedState.PlayerConnected }
)
)
{ {
if (_playerWeaponImage.TryGetValue(player.Slot, out var value) && !string.IsNullOrEmpty(value)) if (_playerWeaponImage.TryGetValue(player.Slot, out var value) && !string.IsNullOrEmpty(value))
{ {

14
IDatabaseConnection.cs Normal file
View File

@@ -0,0 +1,14 @@
using System.Data;
namespace WeaponPaints
{
public interface IDatabaseConnection : IAsyncDisposable, IDisposable
{
Task OpenAsync();
Task CloseAsync();
Task<IDbTransaction> BeginTransactionAsync();
Task CommitTransactionAsync(IDbTransaction transaction);
Task RollbackTransactionAsync(IDbTransaction transaction);
IDbConnection GetConnection();
}
}

68
MySQLConnection.cs Normal file
View File

@@ -0,0 +1,68 @@
using Microsoft.Extensions.Logging;
using MySqlConnector;
using System.Data;
namespace WeaponPaints
{
public class MySQLConnection : IDatabaseConnection
{
private readonly MySqlConnection _connection;
private readonly ILogger _logger;
public MySQLConnection(string connectionString, ILogger logger)
{
_connection = new MySqlConnection(connectionString);
_logger = logger;
}
public async Task OpenAsync()
{
try
{
await _connection.OpenAsync();
}
catch (Exception ex)
{
_logger.LogError($"Unable to connect to MySQL database: {ex.Message}");
throw;
}
}
public async Task CloseAsync()
{
await _connection.CloseAsync();
}
public async Task<IDbTransaction> BeginTransactionAsync()
{
return await _connection.BeginTransactionAsync();
}
public Task CommitTransactionAsync(IDbTransaction transaction)
{
transaction.Commit();
return Task.CompletedTask;
}
public Task RollbackTransactionAsync(IDbTransaction transaction)
{
transaction.Rollback();
return Task.CompletedTask;
}
public IDbConnection GetConnection()
{
return _connection;
}
public void Dispose()
{
_connection?.Dispose();
}
public async ValueTask DisposeAsync()
{
await _connection.DisposeAsync();
}
}
}

68
SQLiteConnection.cs Normal file
View File

@@ -0,0 +1,68 @@
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging;
using System.Data;
namespace WeaponPaints
{
public class SQLiteConnection : IDatabaseConnection
{
private readonly Microsoft.Data.Sqlite.SqliteConnection _connection;
private readonly ILogger _logger;
public SQLiteConnection(string connectionString, ILogger logger)
{
_connection = new Microsoft.Data.Sqlite.SqliteConnection(connectionString);
_logger = logger;
}
public async Task OpenAsync()
{
try
{
await _connection.OpenAsync();
}
catch (Exception ex)
{
_logger.LogError($"Unable to connect to SQLite database: {ex.Message}");
throw;
}
}
public async Task CloseAsync()
{
await _connection.CloseAsync();
}
public async Task<IDbTransaction> BeginTransactionAsync()
{
return await _connection.BeginTransactionAsync();
}
public Task CommitTransactionAsync(IDbTransaction transaction)
{
transaction.Commit();
return Task.CompletedTask;
}
public Task RollbackTransactionAsync(IDbTransaction transaction)
{
transaction.Rollback();
return Task.CompletedTask;
}
public IDbConnection GetConnection()
{
return _connection;
}
public void Dispose()
{
_connection?.Dispose();
}
public async ValueTask DisposeAsync()
{
await _connection.DisposeAsync();
}
}
}

View File

@@ -20,89 +20,166 @@ namespace WeaponPaints
try try
{ {
await using var connection = await WeaponPaints.Database.GetConnectionAsync(); await using var connection = await WeaponPaints.Database.GetConnectionAsync();
await using var transaction = await connection.BeginTransactionAsync(); string[] createTableQueries = GetCreateTableQueries();
// Log para debug
WeaponPaints.Instance.Logger.LogInformation($"[WeaponPaints] Creating {createTableQueries.Length} tables for {Config?.DatabaseType} database");
try foreach (var query in createTableQueries)
{ {
string[] createTableQueries = try
[
@"
CREATE TABLE IF NOT EXISTS `wp_player_skins` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`weapon_defindex` int(6) NOT NULL,
`weapon_paint_id` int(6) NOT NULL,
`weapon_wear` float NOT NULL DEFAULT 0.000001,
`weapon_seed` int(16) NOT NULL DEFAULT 0,
`weapon_nametag` VARCHAR(128) DEFAULT NULL,
`weapon_stattrak` tinyint(1) NOT NULL DEFAULT 0,
`weapon_stattrak_count` int(10) NOT NULL DEFAULT 0,
`weapon_sticker_0` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_1` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_2` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_3` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_4` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_keychain` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0' COMMENT 'id;x;y;z;seed',
UNIQUE (`steamid`, `weapon_team`, `weapon_defindex`) -- Add unique constraint here
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_knife` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`knife` varchar(64) NOT NULL,
UNIQUE (`steamid`, `weapon_team`) -- Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`weapon_defindex` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`) -- Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_agents` (
`steamid` varchar(18) NOT NULL,
`agent_ct` varchar(64) DEFAULT NULL,
`agent_t` varchar(64) DEFAULT NULL,
UNIQUE (`steamid`) -- Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_music` (
`steamid` varchar(64) NOT NULL,
`weapon_team` int(1) NOT NULL,
`music_id` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`) -- Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_pins` (
`steamid` varchar(64) NOT NULL,
`weapon_team` int(1) NOT NULL,
`id` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`) -- Unique constraint
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;"
];
foreach (var query in createTableQueries)
{ {
await connection.ExecuteAsync(query, transaction: transaction); await connection.GetConnection().ExecuteAsync(query);
WeaponPaints.Instance.Logger.LogInformation($"[WeaponPaints] Table created successfully");
} }
catch (Exception ex)
{
WeaponPaints.Instance.Logger.LogError($"[WeaponPaints] Error creating table: {ex.Message}");
WeaponPaints.Instance.Logger.LogError($"[WeaponPaints] Query: {query}");
throw;
}
}
await transaction.CommitAsync(); WeaponPaints.Instance.Logger.LogInformation("[WeaponPaints] All database tables created successfully");
}
catch (Exception)
{
await transaction.RollbackAsync();
throw new Exception("[WeaponPaints] Unable to create tables!");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("[WeaponPaints] Unknown MySQL exception! " + ex.Message); WeaponPaints.Instance.Logger.LogError($"[WeaponPaints] Database exception: {ex.Message}");
throw new Exception("[WeaponPaints] Unknown database exception! " + ex.Message);
}
}
private static string[] GetCreateTableQueries()
{
if (Config?.DatabaseType?.ToLower() == "sqlite")
{
return new string[]
{
@"
CREATE TABLE IF NOT EXISTS wp_player_skins (
steamid TEXT NOT NULL,
weapon_team INTEGER NOT NULL,
weapon_defindex INTEGER NOT NULL,
weapon_paint_id INTEGER NOT NULL,
weapon_wear REAL NOT NULL DEFAULT 0.000001,
weapon_seed INTEGER NOT NULL DEFAULT 0,
weapon_nametag TEXT DEFAULT NULL,
weapon_stattrak INTEGER NOT NULL DEFAULT 0,
weapon_stattrak_count INTEGER NOT NULL DEFAULT 0,
weapon_sticker_0 TEXT NOT NULL DEFAULT '0;0;0;0;0;0;0',
weapon_sticker_1 TEXT NOT NULL DEFAULT '0;0;0;0;0;0;0',
weapon_sticker_2 TEXT NOT NULL DEFAULT '0;0;0;0;0;0;0',
weapon_sticker_3 TEXT NOT NULL DEFAULT '0;0;0;0;0;0;0',
weapon_sticker_4 TEXT NOT NULL DEFAULT '0;0;0;0;0;0;0',
weapon_keychain TEXT NOT NULL DEFAULT '0;0;0;0;0',
UNIQUE (steamid, weapon_team, weapon_defindex)
)",
@"
CREATE TABLE IF NOT EXISTS wp_player_knife (
steamid TEXT NOT NULL,
weapon_team INTEGER NOT NULL,
knife TEXT NOT NULL,
UNIQUE (steamid, weapon_team)
)",
@"
CREATE TABLE IF NOT EXISTS wp_player_gloves (
steamid TEXT NOT NULL,
weapon_team INTEGER NOT NULL,
weapon_defindex INTEGER NOT NULL,
UNIQUE (steamid, weapon_team)
)",
@"
CREATE TABLE IF NOT EXISTS wp_player_agents (
steamid TEXT NOT NULL,
agent_ct TEXT DEFAULT NULL,
agent_t TEXT DEFAULT NULL,
UNIQUE (steamid)
)",
@"
CREATE TABLE IF NOT EXISTS wp_player_music (
steamid TEXT NOT NULL,
weapon_team INTEGER NOT NULL,
music_id INTEGER NOT NULL,
UNIQUE (steamid, weapon_team)
)",
@"
CREATE TABLE IF NOT EXISTS wp_player_pins (
steamid TEXT NOT NULL,
weapon_team INTEGER NOT NULL,
id INTEGER NOT NULL,
UNIQUE (steamid, weapon_team)
)"
};
}
else // MySQL
{
return new string[]
{
@"
CREATE TABLE IF NOT EXISTS `wp_player_skins` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`weapon_defindex` int(6) NOT NULL,
`weapon_paint_id` int(6) NOT NULL,
`weapon_wear` float NOT NULL DEFAULT 0.000001,
`weapon_seed` int(16) NOT NULL DEFAULT 0,
`weapon_nametag` VARCHAR(128) DEFAULT NULL,
`weapon_stattrak` tinyint(1) NOT NULL DEFAULT 0,
`weapon_stattrak_count` int(10) NOT NULL DEFAULT 0,
`weapon_sticker_0` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_1` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_2` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_3` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_4` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_keychain` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0' COMMENT 'id;x;y;z;seed',
UNIQUE (`steamid`, `weapon_team`, `weapon_defindex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_knife` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`knife` varchar(64) NOT NULL,
UNIQUE (`steamid`, `weapon_team`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
`steamid` varchar(18) NOT NULL,
`weapon_team` int(1) NOT NULL,
`weapon_defindex` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_agents` (
`steamid` varchar(18) NOT NULL,
`agent_ct` varchar(64) DEFAULT NULL,
`agent_t` varchar(64) DEFAULT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_music` (
`steamid` varchar(64) NOT NULL,
`weapon_team` int(1) NOT NULL,
`music_id` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;",
@"
CREATE TABLE IF NOT EXISTS `wp_player_pins` (
`steamid` varchar(64) NOT NULL,
`weapon_team` int(1) NOT NULL,
`id` int(11) NOT NULL,
UNIQUE (`steamid`, `weapon_team`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;"
};
} }
} }

View File

@@ -168,4 +168,6 @@ public partial class WeaponPaints
private static readonly PluginCapability<IMenuApi> MenuCapability = new("menu:nfcore"); private static readonly PluginCapability<IMenuApi> MenuCapability = new("menu:nfcore");
private int _fadeSeed; private int _fadeSeed;
internal List<CCSPlayerController> Players = [];
} }

View File

@@ -452,12 +452,11 @@ namespace WeaponPaints
private void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false) private void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false)
{ {
if (!weapon.DesignerName.Contains("ak47")) return;
if (weapon.CBodyComponent?.SceneNode == null) return; if (weapon.CBodyComponent?.SceneNode == null) return;
var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance(); //var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance();
// skeleton.ModelState.MeshGroupMask = isLegacy ? 2UL : 1UL;
weapon.AcceptInput("SetBodygroup", value: $"body,{(isLegacy ? 1 : 0)}"); weapon.AcceptInput("SetBodygroup", value: $"body,{(isLegacy ? 1 : 0)}");
// skeleton.ModelState.MeshGroupMask = isLegacy ? 2UL : 1UL;
} }
private void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy) private void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy)
@@ -595,4 +594,4 @@ namespace WeaponPaints
return BitConverter.Int32BitsToSingle((int)value); return BitConverter.Int32BitsToSingle((int)value);
} }
} }
} }

View File

@@ -80,9 +80,28 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
Config = config; Config = config;
_config = config; _config = config;
if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1) // Validar configurações de banco de dados
if (config.DatabaseType.ToLower() == "mysql")
{ {
Logger.LogError("You need to setup Database credentials in \"configs/plugins/WeaponPaints/WeaponPaints.json\"!"); if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
{
Logger.LogError("You need to setup MySQL Database credentials in \"configs/plugins/WeaponPaints/WeaponPaints.json\"!");
Unload(false);
return;
}
}
else if (config.DatabaseType.ToLower() == "sqlite")
{
if (string.IsNullOrEmpty(config.DatabasePath))
{
Logger.LogError("You need to setup SQLite Database path in \"configs/plugins/WeaponPaints/WeaponPaints.json\"!");
Unload(false);
return;
}
}
else
{
Logger.LogError("Invalid DatabaseType. Use 'mysql' or 'sqlite'.");
Unload(false); Unload(false);
return; return;
} }
@@ -94,23 +113,43 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
return; return;
} }
var builder = new MySqlConnectionStringBuilder // Criar conexão baseada no tipo de banco
IDatabaseConnection connection;
if (config.DatabaseType.ToLower() == "mysql")
{ {
Server = config.DatabaseHost, var builder = new MySqlConnectionStringBuilder
UserID = config.DatabaseUser, {
Password = config.DatabasePassword, Server = config.DatabaseHost,
Database = config.DatabaseName, UserID = config.DatabaseUser,
Port = (uint)config.DatabasePort, Password = config.DatabasePassword,
Pooling = true, Database = config.DatabaseName,
MaximumPoolSize = 640, Port = (uint)config.DatabasePort,
}; Pooling = true,
MaximumPoolSize = 640,
};
connection = new MySQLConnection(builder.ConnectionString, Logger);
}
else // SQLite
{
// Garantir que o diretório existe
var dbPath = Path.GetFullPath(config.DatabasePath);
var dbDirectory = Path.GetDirectoryName(dbPath);
if (!string.IsNullOrEmpty(dbDirectory) && !Directory.Exists(dbDirectory))
{
Directory.CreateDirectory(dbDirectory);
}
var connectionString = $"Data Source={dbPath}";
Logger.LogInformation($"[WeaponPaints] SQLite database path: {dbPath}");
connection = new SQLiteConnection(connectionString, Logger);
}
Database = new Database(builder.ConnectionString); Database = new Database(connection);
_ = Utility.CheckDatabaseTables();
_localizer = Localizer;
Utility.Config = config; Utility.Config = config;
Task.Run(async () => await Utility.CheckDatabaseTables());
_localizer = Localizer;
Utility.ShowAd(ModuleVersion); Utility.ShowAd(ModuleVersion);
Task.Run(async () => await Utility.CheckVersion(ModuleVersion, Logger)); Task.Run(async () => await Utility.CheckVersion(ModuleVersion, Logger));
} }

View File

@@ -9,10 +9,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.339" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.342" />
<PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="MySqlConnector" Version="2.4.0-beta.1" /> <PackageReference Include="MySqlConnector" Version="2.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

37
WeaponPaints.json Normal file
View File

@@ -0,0 +1,37 @@
{
"ConfigVersion": 10,
"SkinsLanguage": "pt-BR",
"DatabaseType": "sqlite",
"DatabasePath": "weaponpaints.db",
"DatabaseHost": "",
"DatabasePort": 3306,
"DatabaseUser": "",
"DatabasePassword": "",
"DatabaseName": "",
"CmdRefreshCooldownSeconds": 3,
"Website": "example.com/skins",
"Additional": {
"KnifeEnabled": true,
"GloveEnabled": true,
"MusicEnabled": true,
"AgentEnabled": true,
"SkinEnabled": true,
"PinsEnabled": true,
"CommandWpEnabled": true,
"CommandKillEnabled": true,
"CommandKnife": ["knife"],
"CommandMusic": ["music"],
"CommandPin": ["pin", "pins", "coin", "coins"],
"CommandGlove": ["gloves"],
"CommandAgent": ["agents"],
"CommandStattrak": ["stattrak", "st"],
"CommandSkin": ["ws"],
"CommandSkinSelection": ["skins"],
"CommandRefresh": ["wp"],
"CommandKill": ["kill"],
"GiveRandomKnife": false,
"GiveRandomSkin": false,
"ShowSkinImage": true
},
"MenuType": "selectable"
}

View File

@@ -1,6 +1,11 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005Cxdaff_005CDocuments_005CGitHub_005Ccs2_002DWeaponPaints_005C3rd_005Fparty_005CMenuManagerApi_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005Cxdaff_005CDocuments_005CGitHub_005Ccs2_002DWeaponPaints_005C3rd_005Fparty_005CMenuManagerApi_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACBaseAnimGraph_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fedce4cda20b83aa28fbed15b81eb0eda1753e497144879a4bd754947d37639_003FCBaseAnimGraph_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACBaseAnimGraph_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fedce4cda20b83aa28fbed15b81eb0eda1753e497144879a4bd754947d37639_003FCBaseAnimGraph_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACBaseEntity_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdd25ac51dad807865e0d135626a4fd984d63a388bf0c3285f9d7d7db9c1071_003FCBaseEntity_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACBodyComponent_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdb7e149cad83cf211ee55349a3442256ec62acce5ba41474ad124572f767e271_003FCBodyComponent_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACBodyComponent_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdb7e149cad83cf211ee55349a3442256ec62acce5ba41474ad124572f767e271_003FCBodyComponent_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACCSPlayerController_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fab13f7aee75d35b3ec314a3fd92a24c4c0126cef65a8dda49bd83da5a2a77443_003FCCSPlayerController_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACCSPlayerController_005FInventoryServices_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fff255772feb17b2ef53224c45249eee339ad7148e2b42bb1afad71bd57d02b69_003FCCSPlayerController_005FInventoryServices_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACGameSceneNode_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F343a4f176a269193769d7fd81231808c83529cab0f6c98fd96eb77f558974_003FCGameSceneNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACModelState_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fb03ffa24c03867c84b5d095397bd1578b8ea563ab2c72b30242ffad815d49e_003FCModelState_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACModelState_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fb03ffa24c03867c84b5d095397bd1578b8ea563ab2c72b30242ffad815d49e_003FCModelState_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AListeners_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdbb2ccedd8f0b227a69f9ef0b434aa5a70b83e93bf1eac4cd91a31b7985efd4_003FListeners_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkedVector_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fd68dbf9c04bc6046e155f1866c3615a47e34017f330c9e351d68979b9281c_003FNetworkedVector_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkedVector_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fd68dbf9c04bc6046e155f1866c3615a47e34017f330c9e351d68979b9281c_003FNetworkedVector_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -1,8 +1,8 @@
using Dapper; using Dapper;
using MySqlConnector;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using System.Globalization; using System.Globalization;
using System.Data;
namespace WeaponPaints; namespace WeaponPaints;
@@ -24,17 +24,17 @@ internal class WeaponSynchronization
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
if (_config.Additional.KnifeEnabled) if (_config.Additional.KnifeEnabled)
GetKnifeFromDatabase(player, connection); GetKnifeFromDatabase(player, connection.GetConnection());
if (_config.Additional.GloveEnabled) if (_config.Additional.GloveEnabled)
GetGloveFromDatabase(player, connection); GetGloveFromDatabase(player, connection.GetConnection());
if (_config.Additional.AgentEnabled) if (_config.Additional.AgentEnabled)
GetAgentFromDatabase(player, connection); GetAgentFromDatabase(player, connection.GetConnection());
if (_config.Additional.MusicEnabled) if (_config.Additional.MusicEnabled)
GetMusicFromDatabase(player, connection); GetMusicFromDatabase(player, connection.GetConnection());
if (_config.Additional.SkinEnabled) if (_config.Additional.SkinEnabled)
GetWeaponPaintsFromDatabase(player, connection); GetWeaponPaintsFromDatabase(player, connection.GetConnection());
if (_config.Additional.PinsEnabled) if (_config.Additional.PinsEnabled)
GetPinsFromDatabase(player, connection); GetPinsFromDatabase(player, connection.GetConnection());
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -43,14 +43,16 @@ internal class WeaponSynchronization
} }
} }
private void GetKnifeFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetKnifeFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `knife`, `weapon_team` FROM `wp_player_knife` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT knife, weapon_team FROM wp_player_knife WHERE steamid = @steamid ORDER BY weapon_team ASC"
: "SELECT `knife`, `weapon_team` FROM `wp_player_knife` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC";
var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player
foreach (var row in rows) foreach (var row in rows)
@@ -59,14 +61,14 @@ internal class WeaponSynchronization
if (string.IsNullOrEmpty(row.knife)) continue; if (string.IsNullOrEmpty(row.knife)) continue;
// Determine the weapon team based on the query result // Determine the weapon team based on the query result
CsTeam weaponTeam = (int)row.weapon_team switch CsTeam weaponTeam = Convert.ToInt32(row.weapon_team) switch
{ {
2 => CsTeam.Terrorist, 2 => CsTeam.Terrorist,
3 => CsTeam.CounterTerrorist, 3 => CsTeam.CounterTerrorist,
_ => CsTeam.None, _ => CsTeam.None,
}; };
// Get or create entries for the players slot // Get or create entries for the player's slot
var playerKnives = WeaponPaints.GPlayersKnife.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, string>()); var playerKnives = WeaponPaints.GPlayersKnife.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, string>());
if (weaponTeam == CsTeam.None) if (weaponTeam == CsTeam.None)
@@ -88,14 +90,16 @@ internal class WeaponSynchronization
} }
} }
private void GetGloveFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetGloveFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `weapon_defindex`, `weapon_team` FROM `wp_player_gloves` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT weapon_defindex, weapon_team FROM wp_player_gloves WHERE steamid = @steamid ORDER BY weapon_team ASC"
: "SELECT `weapon_defindex`, `weapon_team` FROM `wp_player_gloves` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC";
var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player
foreach (var row in rows) foreach (var row in rows)
@@ -104,7 +108,7 @@ internal class WeaponSynchronization
if (row.weapon_defindex == null) continue; if (row.weapon_defindex == null) continue;
// Determine the weapon team based on the query result // Determine the weapon team based on the query result
var playerGloves = WeaponPaints.GPlayersGlove.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>()); var playerGloves = WeaponPaints.GPlayersGlove.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>());
CsTeam weaponTeam = (int)row.weapon_team switch CsTeam weaponTeam = Convert.ToInt32(row.weapon_team) switch
{ {
2 => CsTeam.Terrorist, 2 => CsTeam.Terrorist,
3 => CsTeam.CounterTerrorist, 3 => CsTeam.CounterTerrorist,
@@ -116,13 +120,13 @@ internal class WeaponSynchronization
if (weaponTeam == CsTeam.None) if (weaponTeam == CsTeam.None)
{ {
// Assign glove ID to both teams if weaponTeam is None // Assign glove ID to both teams if weaponTeam is None
playerGloves[CsTeam.Terrorist] = (ushort)row.weapon_defindex; playerGloves[CsTeam.Terrorist] = Convert.ToUInt16(row.weapon_defindex);
playerGloves[CsTeam.CounterTerrorist] = (ushort)row.weapon_defindex; playerGloves[CsTeam.CounterTerrorist] = Convert.ToUInt16(row.weapon_defindex);
} }
else else
{ {
// Assign glove ID to the specific team // Assign glove ID to the specific team
playerGloves[weaponTeam] = (ushort)row.weapon_defindex; playerGloves[weaponTeam] = Convert.ToUInt16(row.weapon_defindex);
} }
} }
} }
@@ -132,14 +136,16 @@ internal class WeaponSynchronization
} }
} }
private void GetAgentFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetAgentFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `agent_ct`, `agent_t` FROM `wp_player_agents` WHERE `steamid` = @steamid"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT agent_ct, agent_t FROM wp_player_agents WHERE steamid = @steamid"
: "SELECT `agent_ct`, `agent_t` FROM `wp_player_agents` WHERE `steamid` = @steamid";
var agentData = connection.QueryFirstOrDefault<(string, string)>(query, new { steamid = player.SteamId }); var agentData = connection.QueryFirstOrDefault<(string, string)>(query, new { steamid = player.SteamId });
if (agentData == default) return; if (agentData == default) return;
@@ -160,7 +166,7 @@ internal class WeaponSynchronization
} }
} }
private void GetWeaponPaintsFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetWeaponPaintsFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
@@ -172,20 +178,22 @@ internal class WeaponSynchronization
// var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>(); // var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>();
const string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT * FROM wp_player_skins WHERE steamid = @steamid ORDER BY weapon_team ASC"
: "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC";
var playerSkins = connection.Query<dynamic>(query, new { steamid = player.SteamId }); var playerSkins = connection.Query<dynamic>(query, new { steamid = player.SteamId });
foreach (var row in playerSkins) foreach (var row in playerSkins)
{ {
int weaponDefIndex = row.weapon_defindex ?? 0; int weaponDefIndex = Convert.ToInt32(row.weapon_defindex ?? 0);
int weaponPaintId = row.weapon_paint_id ?? 0; int weaponPaintId = Convert.ToInt32(row.weapon_paint_id ?? 0);
float weaponWear = row.weapon_wear ?? 0f; float weaponWear = Convert.ToSingle(row.weapon_wear ?? 0f);
int weaponSeed = row.weapon_seed ?? 0; int weaponSeed = Convert.ToInt32(row.weapon_seed ?? 0);
string weaponNameTag = row.weapon_nametag ?? ""; string weaponNameTag = row.weapon_nametag?.ToString() ?? "";
bool weaponStatTrak = row.weapon_stattrak ?? false; bool weaponStatTrak = Convert.ToBoolean(row.weapon_stattrak ?? false);
int weaponStatTrakCount = row.weapon_stattrak_count ?? 0; int weaponStatTrakCount = Convert.ToInt32(row.weapon_stattrak_count ?? 0);
CsTeam weaponTeam = row.weapon_team switch CsTeam weaponTeam = Convert.ToInt32(row.weapon_team) switch
{ {
2 => CsTeam.Terrorist, 2 => CsTeam.Terrorist,
3 => CsTeam.CounterTerrorist, 3 => CsTeam.CounterTerrorist,
@@ -295,14 +303,16 @@ internal class WeaponSynchronization
} }
} }
private void GetMusicFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetMusicFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `music_id`, `weapon_team` FROM `wp_player_music` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT music_id, weapon_team FROM wp_player_music WHERE steamid = @steamid ORDER BY weapon_team ASC"
: "SELECT `music_id`, `weapon_team` FROM `wp_player_music` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC";
var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player
foreach (var row in rows) foreach (var row in rows)
@@ -311,26 +321,26 @@ internal class WeaponSynchronization
if (row.music_id == null) continue; if (row.music_id == null) continue;
// Determine the weapon team based on the query result // Determine the weapon team based on the query result
CsTeam weaponTeam = (int)row.weapon_team switch CsTeam weaponTeam = Convert.ToInt32(row.weapon_team) switch
{ {
2 => CsTeam.Terrorist, 2 => CsTeam.Terrorist,
3 => CsTeam.CounterTerrorist, 3 => CsTeam.CounterTerrorist,
_ => CsTeam.None, _ => CsTeam.None,
}; };
// Get or create entries for the players slot // Get or create entries for the player's slot
var playerMusic = WeaponPaints.GPlayersMusic.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>()); var playerMusic = WeaponPaints.GPlayersMusic.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>());
if (weaponTeam == CsTeam.None) if (weaponTeam == CsTeam.None)
{ {
// Assign music ID to both teams if weaponTeam is None // Assign music ID to both teams if weaponTeam is None
playerMusic[CsTeam.Terrorist] = (ushort)row.music_id; playerMusic[CsTeam.Terrorist] = Convert.ToUInt16(row.music_id);
playerMusic[CsTeam.CounterTerrorist] = (ushort)row.music_id; playerMusic[CsTeam.CounterTerrorist] = Convert.ToUInt16(row.music_id);
} }
else else
{ {
// Assign music ID to the specific team // Assign music ID to the specific team
playerMusic[weaponTeam] = (ushort)row.music_id; playerMusic[weaponTeam] = Convert.ToUInt16(row.music_id);
} }
} }
} }
@@ -340,14 +350,16 @@ internal class WeaponSynchronization
} }
} }
private void GetPinsFromDatabase(PlayerInfo? player, MySqlConnection connection) private void GetPinsFromDatabase(PlayerInfo? player, IDbConnection connection)
{ {
try try
{ {
if (string.IsNullOrEmpty(player?.SteamId)) if (string.IsNullOrEmpty(player?.SteamId))
return; return;
const string query = "SELECT `id`, `weapon_team` FROM `wp_player_pins` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT id, weapon_team FROM wp_player_pins WHERE steamid = @steamid ORDER BY weapon_team ASC"
: "SELECT `id`, `weapon_team` FROM `wp_player_pins` WHERE `steamid` = @steamid ORDER BY `weapon_team` ASC";
var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player var rows = connection.Query<dynamic>(query, new { steamid = player.SteamId }); // Retrieve all records for the player
foreach (var row in rows) foreach (var row in rows)
@@ -356,26 +368,26 @@ internal class WeaponSynchronization
if (row.id == null) continue; if (row.id == null) continue;
// Determine the weapon team based on the query result // Determine the weapon team based on the query result
CsTeam weaponTeam = (int)row.weapon_team switch CsTeam weaponTeam = Convert.ToInt32(row.weapon_team) switch
{ {
2 => CsTeam.Terrorist, 2 => CsTeam.Terrorist,
3 => CsTeam.CounterTerrorist, 3 => CsTeam.CounterTerrorist,
_ => CsTeam.None, _ => CsTeam.None,
}; };
// Get or create entries for the players slot // Get or create entries for the player's slot
var playerPins = WeaponPaints.GPlayersPin.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>()); var playerPins = WeaponPaints.GPlayersPin.GetOrAdd(player.Slot, _ => new ConcurrentDictionary<CsTeam, ushort>());
if (weaponTeam == CsTeam.None) if (weaponTeam == CsTeam.None)
{ {
// Assign pin ID to both teams if weaponTeam is None // Assign pin ID to both teams if weaponTeam is None
playerPins[CsTeam.Terrorist] = (ushort)row.id; playerPins[CsTeam.Terrorist] = Convert.ToUInt16(row.id);
playerPins[CsTeam.CounterTerrorist] = (ushort)row.id; playerPins[CsTeam.CounterTerrorist] = Convert.ToUInt16(row.id);
} }
else else
{ {
// Assign pin ID to the specific team // Assign pin ID to the specific team
playerPins[weaponTeam] = (ushort)row.id; playerPins[weaponTeam] = Convert.ToUInt16(row.id);
} }
} }
} }
@@ -389,7 +401,9 @@ internal class WeaponSynchronization
{ {
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife) || teams.Length == 0) return; if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife) || teams.Length == 0) return;
const string query = "INSERT INTO `wp_player_knife` (`steamid`, `weapon_team`, `knife`) VALUES(@steamid, @team, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "INSERT OR REPLACE INTO wp_player_knife (steamid, weapon_team, knife) VALUES(@steamid, @team, @newKnife)"
: "INSERT INTO `wp_player_knife` (`steamid`, `weapon_team`, `knife`) VALUES(@steamid, @team, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
try try
{ {
@@ -398,7 +412,7 @@ internal class WeaponSynchronization
// Loop through each team and insert/update accordingly // Loop through each team and insert/update accordingly
foreach (var team in teams) foreach (var team in teams)
{ {
await connection.ExecuteAsync(query, new { steamid = player.SteamId, team, newKnife = knife }); await connection.GetConnection().ExecuteAsync(query, new { steamid = player.SteamId, team, newKnife = knife });
} }
} }
catch (Exception e) catch (Exception e)
@@ -413,8 +427,9 @@ internal class WeaponSynchronization
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player.SteamId) || teams.Length == 0) if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player.SteamId) || teams.Length == 0)
return; return;
const string query = @" string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
INSERT INTO `wp_player_gloves` (`steamid`, `weapon_team`, `weapon_defindex`) ? "INSERT OR REPLACE INTO wp_player_gloves (steamid, weapon_team, weapon_defindex) VALUES(@steamid, @team, @gloveDefIndex)"
: @"INSERT INTO `wp_player_gloves` (`steamid`, `weapon_team`, `weapon_defindex`)
VALUES(@steamid, @team, @gloveDefIndex) VALUES(@steamid, @team, @gloveDefIndex)
ON DUPLICATE KEY UPDATE `weapon_defindex` = @gloveDefIndex"; ON DUPLICATE KEY UPDATE `weapon_defindex` = @gloveDefIndex";
@@ -427,7 +442,7 @@ internal class WeaponSynchronization
foreach (var team in teams) foreach (var team in teams)
{ {
// Execute the SQL command for each team // Execute the SQL command for each team
await connection.ExecuteAsync(query, new { await connection.GetConnection().ExecuteAsync(query, new {
steamid = player.SteamId, steamid = player.SteamId,
team = (int)team, // Cast the CsTeam enum to int for insertion team = (int)team, // Cast the CsTeam enum to int for insertion
gloveDefIndex gloveDefIndex
@@ -445,18 +460,14 @@ internal class WeaponSynchronization
{ {
if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player.SteamId)) return;
const string query = """ string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
INSERT INTO `wp_player_agents` (`steamid`, `agent_ct`, `agent_t`) ? "INSERT OR REPLACE INTO wp_player_agents (steamid, agent_ct, agent_t) VALUES(@steamid, @agent_ct, @agent_t)"
VALUES(@steamid, @agent_ct, @agent_t) : "INSERT INTO `wp_player_agents` (`steamid`, `agent_ct`, `agent_t`) VALUES(@steamid, @agent_ct, @agent_t) ON DUPLICATE KEY UPDATE `agent_ct` = @agent_ct, `agent_t` = @agent_t";
ON DUPLICATE KEY UPDATE
`agent_ct` = @agent_ct,
`agent_t` = @agent_t
""";
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
await connection.ExecuteAsync(query, new { steamid = player.SteamId, agent_ct = WeaponPaints.GPlayersAgent[player.Slot].CT, agent_t = WeaponPaints.GPlayersAgent[player.Slot].T }); await connection.GetConnection().ExecuteAsync(query, new { steamid = player.SteamId, agent_ct = WeaponPaints.GPlayersAgent[player.Slot].CT, agent_t = WeaponPaints.GPlayersAgent[player.Slot].T });
} }
catch (Exception e) catch (Exception e)
{ {
@@ -483,9 +494,11 @@ internal class WeaponSynchronization
var seed = weaponInfo.Seed; var seed = weaponInfo.Seed;
// Prepare the queries to check and update/insert weapon skin data // Prepare the queries to check and update/insert weapon skin data
const string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex AND `weapon_team` = @weaponTeam"; string queryCheckExistence = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "SELECT COUNT(*) FROM wp_player_skins WHERE steamid = @steamid AND weapon_defindex = @weaponDefIndex AND weapon_team = @weaponTeam"
: "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex AND `weapon_team` = @weaponTeam";
var existingRecordCount = await connection.ExecuteScalarAsync<int>( var existingRecordCount = await connection.GetConnection().ExecuteScalarAsync<int>(
queryCheckExistence, queryCheckExistence,
new { steamid = player.SteamId, weaponDefIndex, weaponTeam = teamId } new { steamid = player.SteamId, weaponDefIndex, weaponTeam = teamId }
); );
@@ -496,19 +509,21 @@ internal class WeaponSynchronization
if (existingRecordCount > 0) if (existingRecordCount > 0)
{ {
// Update existing record // Update existing record
query = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed " + query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
"WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex AND `weapon_team` = @weaponTeam"; ? "UPDATE wp_player_skins SET weapon_paint_id = @paintId, weapon_wear = @wear, weapon_seed = @seed WHERE steamid = @steamid AND weapon_defindex = @weaponDefIndex AND weapon_team = @weaponTeam"
: "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex AND `weapon_team` = @weaponTeam";
parameters = new { steamid = player.SteamId, weaponDefIndex, weaponTeam = (int)teamId, paintId, wear, seed }; parameters = new { steamid = player.SteamId, weaponDefIndex, weaponTeam = (int)teamId, paintId, wear, seed };
} }
else else
{ {
// Insert new record // Insert new record
query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_team`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " + query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
"VALUES (@steamid, @weaponDefIndex, @weaponTeam, @paintId, @wear, @seed)"; ? "INSERT INTO wp_player_skins (steamid, weapon_defindex, weapon_team, weapon_paint_id, weapon_wear, weapon_seed) VALUES (@steamid, @weaponDefIndex, @weaponTeam, @paintId, @wear, @seed)"
: "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_team`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) VALUES (@steamid, @weaponDefIndex, @weaponTeam, @paintId, @wear, @seed)";
parameters = new { steamid = player.SteamId, weaponDefIndex, weaponTeam = (int)teamId, paintId, wear, seed }; parameters = new { steamid = player.SteamId, weaponDefIndex, weaponTeam = (int)teamId, paintId, wear, seed };
} }
await connection.ExecuteAsync(query, parameters); await connection.GetConnection().ExecuteAsync(query, parameters);
} }
} }
} }
@@ -522,7 +537,9 @@ internal class WeaponSynchronization
{ {
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId)) return;
const string query = "INSERT INTO `wp_player_music` (`steamid`, `weapon_team`, `music_id`) VALUES(@steamid, @team, @newMusic) ON DUPLICATE KEY UPDATE `music_id` = @newMusic"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "INSERT OR REPLACE INTO wp_player_music (steamid, weapon_team, music_id) VALUES(@steamid, @team, @newMusic)"
: "INSERT INTO `wp_player_music` (`steamid`, `weapon_team`, `music_id`) VALUES(@steamid, @team, @newMusic) ON DUPLICATE KEY UPDATE `music_id` = @newMusic";
try try
{ {
@@ -531,7 +548,7 @@ internal class WeaponSynchronization
// Loop through each team and insert/update accordingly // Loop through each team and insert/update accordingly
foreach (var team in teams) foreach (var team in teams)
{ {
await connection.ExecuteAsync(query, new { steamid = player.SteamId, team, newMusic = music }); await connection.GetConnection().ExecuteAsync(query, new { steamid = player.SteamId, team, newMusic = music });
} }
} }
catch (Exception e) catch (Exception e)
@@ -544,7 +561,9 @@ internal class WeaponSynchronization
{ {
if (!_config.Additional.PinsEnabled || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.PinsEnabled || string.IsNullOrEmpty(player.SteamId)) return;
const string query = "INSERT INTO `wp_player_pins` (`steamid`, `weapon_team`, `id`) VALUES(@steamid, @team, @newPin) ON DUPLICATE KEY UPDATE `id` = @newPin"; string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
? "INSERT OR REPLACE INTO wp_player_pins (steamid, weapon_team, id) VALUES(@steamid, @team, @newPin)"
: "INSERT INTO `wp_player_pins` (`steamid`, `weapon_team`, `id`) VALUES(@steamid, @team, @newPin) ON DUPLICATE KEY UPDATE `id` = @newPin";
try try
{ {
@@ -553,7 +572,7 @@ internal class WeaponSynchronization
// Loop through each team and insert/update accordingly // Loop through each team and insert/update accordingly
foreach (var team in teams) foreach (var team in teams)
{ {
await connection.ExecuteAsync(query, new { steamid = player.SteamId, team, newPin = pin }); await connection.GetConnection().ExecuteAsync(query, new { steamid = player.SteamId, team, newPin = pin });
} }
} }
catch (Exception e) catch (Exception e)
@@ -571,7 +590,7 @@ internal class WeaponSynchronization
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
await using var transaction = await connection.BeginTransactionAsync(); using var transaction = await connection.BeginTransactionAsync();
// Check if player's slot exists in GPlayerWeaponsInfo // Check if player's slot exists in GPlayerWeaponsInfo
if (!WeaponPaints.GPlayerWeaponsInfo.TryGetValue(player.Slot, out var teamWeaponsInfo)) if (!WeaponPaints.GPlayerWeaponsInfo.TryGetValue(player.Slot, out var teamWeaponsInfo))
@@ -599,8 +618,9 @@ internal class WeaponSynchronization
// Sync StatTrak values for the current team // Sync StatTrak values for the current team
foreach (var (defindex, (statTrak, statTrakCount)) in statTrakWeapons) foreach (var (defindex, (statTrak, statTrakCount)) in statTrakWeapons)
{ {
const string query = @" string query = Utility.Config?.DatabaseType?.ToLower() == "sqlite"
UPDATE `wp_player_skins` ? "UPDATE wp_player_skins SET weapon_stattrak = @StatTrak, weapon_stattrak_count = @StatTrakCount WHERE steamid = @steamid AND weapon_defindex = @weaponDefIndex AND weapon_team = @weaponTeam"
: @"UPDATE `wp_player_skins`
SET `weapon_stattrak` = @StatTrak, SET `weapon_stattrak` = @StatTrak,
`weapon_stattrak_count` = @StatTrakCount `weapon_stattrak_count` = @StatTrakCount
WHERE `steamid` = @steamid WHERE `steamid` = @steamid
@@ -616,11 +636,11 @@ internal class WeaponSynchronization
weaponTeam weaponTeam
}; };
await connection.ExecuteAsync(query, parameters, transaction); await connection.GetConnection().ExecuteAsync(query, parameters, transaction);
} }
} }
await transaction.CommitAsync(); await connection.CommitTransactionAsync(transaction);
} }
catch (Exception e) catch (Exception e)
{ {