- Minor changes
This commit is contained in:
Dawid Bepierszcz
2024-04-28 02:17:24 +02:00
parent ec0d4f4d5a
commit 29461e9de2
10 changed files with 475 additions and 566 deletions

View File

@@ -14,7 +14,7 @@ namespace WeaponPaints
if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return; if (player == null || !player.IsValid || player.UserId == null || player.IsBot) return;
PlayerInfo playerInfo = new PlayerInfo PlayerInfo? playerInfo = new PlayerInfo
{ {
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
@@ -26,7 +26,7 @@ namespace WeaponPaints
try try
{ {
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (player != null && !commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
@@ -107,11 +107,11 @@ namespace WeaponPaints
player!.Print(Localizer["wp_info_music"]); player!.Print(Localizer["wp_info_music"]);
} }
if (Config.Additional.KnifeEnabled) if (!Config.Additional.KnifeEnabled) return;
if (!string.IsNullOrEmpty(Localizer["wp_info_knife"])) if (!string.IsNullOrEmpty(Localizer["wp_info_knife"]))
{ {
player!.Print(Localizer["wp_info_knife"]); player!.Print(Localizer["wp_info_knife"]);
} }
} }
private void RegisterCommands() private void RegisterCommands()
@@ -141,7 +141,7 @@ namespace WeaponPaints
{ {
if (!Config.Additional.KnifeEnabled || !g_bCommandsAllowed) return; if (!Config.Additional.KnifeEnabled || !g_bCommandsAllowed) return;
var knivesOnly = weaponList var knivesOnly = WeaponList
.Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet")) .Where(pair => pair.Key.StartsWith("weapon_knife") || pair.Key.StartsWith("weapon_bayonet"))
.ToDictionary(pair => pair.Key, pair => pair.Value); .ToDictionary(pair => pair.Key, pair => pair.Value);
@@ -152,36 +152,34 @@ namespace WeaponPaints
var knifeName = option.Text; var knifeName = option.Text;
var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key; var knifeKey = knivesOnly.FirstOrDefault(x => x.Value == knifeName).Key;
if (!string.IsNullOrEmpty(knifeKey)) if (string.IsNullOrEmpty(knifeKey)) return;
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_select"]))
{ {
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_select"])) player!.Print(Localizer["wp_knife_menu_select", knifeName]);
{
player!.Print(Localizer["wp_knife_menu_select", knifeName]);
}
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandKillEnabled)
{
player!.Print(Localizer["wp_knife_menu_kill"]);
}
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
g_playersKnife[player.Slot] = knifeKey;
if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE)
RefreshWeapons(player);
if (weaponSync != null)
_ = Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey));
} }
if (!string.IsNullOrEmpty(Localizer["wp_knife_menu_kill"]) && Config.Additional.CommandKillEnabled)
{
player!.Print(Localizer["wp_knife_menu_kill"]);
}
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
g_playersKnife[player.Slot] = knifeKey;
if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE)
RefreshWeapons(player);
if (weaponSync != null)
_ = Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey));
}; };
foreach (var knifePair in knivesOnly) foreach (var knifePair in knivesOnly)
{ {
@@ -193,8 +191,8 @@ namespace WeaponPaints
if (player == null || player.UserId == null) return; if (player == null || player.UserId == null) return;
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
giveItemMenu.PostSelectAction = PostSelectAction.Close; giveItemMenu.PostSelectAction = PostSelectAction.Close;
@@ -210,7 +208,7 @@ namespace WeaponPaints
private void SetupSkinsMenu() private void SetupSkinsMenu()
{ {
var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); var classNamesByWeapon = WeaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]); var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]);
// Function to handle skin selection for a specific weapon // Function to handle skin selection for a specific weapon
@@ -218,117 +216,110 @@ namespace WeaponPaints
{ {
if (!Utility.IsPlayerValid(player)) return; if (!Utility.IsPlayerValid(player)) return;
string selectedWeapon = option.Text; var selectedWeapon = option.Text;
if (classNamesByWeapon.TryGetValue(selectedWeapon, out string? selectedWeaponClassname)) if (!classNamesByWeapon.TryGetValue(selectedWeapon, out var selectedWeaponClassname)) return;
{ var skinsForSelectedWeapon = skinsList?.Where(skin =>
if (selectedWeaponClassname == null) return;
var skinsForSelectedWeapon = skinsList?.Where(skin =>
skin != null &&
skin.TryGetValue("weapon_name", out var weaponName) && skin.TryGetValue("weapon_name", out var weaponName) &&
weaponName?.ToString() == selectedWeaponClassname weaponName?.ToString() == selectedWeaponClassname
)?.ToList(); )?.ToList();
var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]); var skinSubMenu = new ChatMenu(Localizer["wp_skin_menu_skin_title", selectedWeapon]);
// Function to handle skin selection for the chosen weapon // Function to handle skin selection for the chosen weapon
var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) => var handleSkinSelection = (CCSPlayerController p, ChatMenuOption opt) =>
{
if (!Utility.IsPlayerValid(p)) return;
var steamId = p.SteamID.ToString();
var firstSkin = skinsList?.FirstOrDefault(skin =>
{ {
if (!Utility.IsPlayerValid(p)) return; if (skin.TryGetValue("weapon_name", out var weaponName))
string steamId = p.SteamID.ToString();
var firstSkin = skinsList?.FirstOrDefault(skin =>
{ {
if (skin != null && skin.TryGetValue("weapon_name", out var weaponName)) return weaponName?.ToString() == selectedWeaponClassname;
{
return weaponName?.ToString() == selectedWeaponClassname;
}
return false;
});
string selectedSkin = opt.Text;
string selectedPaintID = selectedSkin.Substring(selectedSkin.LastIndexOf('(') + 1).Trim(')');
if (firstSkin != null &&
firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) &&
weaponDefIndexObj != null &&
int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) &&
int.TryParse(selectedPaintID, out var paintID))
{
if (Config.Additional.ShowSkinImage && skinsList != null)
{
var foundSkin = skinsList.FirstOrDefault(skin =>
((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
((int?)skin?["paint"] ?? 0) == paintID &&
skin?["image"] != null
);
string image = foundSkin?["image"]?.ToString() ?? "";
PlayerWeaponImage[p.Slot] = image;
AddTimer(2.0f, () => PlayerWeaponImage.Remove(p.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
p.Print(Localizer["wp_skin_menu_select", selectedSkin]);
if (!gPlayerWeaponsInfo[p.Slot].ContainsKey(weaponDefIndex))
{
gPlayerWeaponsInfo[p.Slot][weaponDefIndex] = new WeaponInfo();
}
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Paint = paintID;
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Wear = 0.01f;
gPlayerWeaponsInfo[p.Slot][weaponDefIndex].Seed = 0;
PlayerInfo playerInfo = new PlayerInfo
{
UserId = p.UserId,
Slot = p.Slot,
Index = (int)p.Index,
SteamId = p.SteamID.ToString(),
Name = p.PlayerName,
IpAddress = p.IpAddress?.Split(":")[0]
};
if (g_bCommandsAllowed && (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && weaponSync != null)
{
RefreshWeapons(player);
try
{
_ = Task.Run(async () => await weaponSync.SyncWeaponPaintsToDatabase(playerInfo));
}
catch (Exception ex)
{
Utility.Log($"Error syncing weapon paints: {ex.Message}");
}
}
} }
}; return false;
});
// Add skin options to the submenu for the selected weapon var selectedSkin = opt.Text;
if (skinsForSelectedWeapon != null) var selectedPaintId = selectedSkin[(selectedSkin.LastIndexOf('(') + 1)..].Trim(')');
if (firstSkin == null ||
!firstSkin.TryGetValue("weapon_defindex", out var weaponDefIndexObj) ||
!int.TryParse(weaponDefIndexObj.ToString(), out var weaponDefIndex) ||
!int.TryParse(selectedPaintId, out var paintId)) return;
{ {
foreach (var skin in skinsForSelectedWeapon.Where(s => s != null)) if (Config.Additional.ShowSkinImage && skinsList != null)
{ {
if (skin.TryGetValue("paint_name", out var paintNameObj) && skin.TryGetValue("paint", out var paintObj)) var foundSkin = skinsList.FirstOrDefault(skin =>
{ ((int?)skin?["weapon_defindex"] ?? 0) == weaponDefIndex &&
var paintName = paintNameObj?.ToString(); ((int?)skin?["paint"] ?? 0) == paintId &&
var paint = paintObj?.ToString(); skin?["image"] != null
);
var image = foundSkin?["image"]?.ToString() ?? "";
PlayerWeaponImage[p.Slot] = image;
AddTimer(2.0f, () => PlayerWeaponImage.Remove(p.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint)) p.Print(Localizer["wp_skin_menu_select", selectedSkin]);
{
skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection); if (!gPlayerWeaponsInfo[p.Slot].TryGetValue(weaponDefIndex, out var value))
} {
} value = new WeaponInfo();
gPlayerWeaponsInfo[p.Slot][weaponDefIndex] = value;
}
value.Paint = paintId;
value.Wear = 0.01f;
value.Seed = 0;
PlayerInfo playerInfo = new PlayerInfo
{
UserId = p.UserId,
Slot = p.Slot,
Index = (int)p.Index,
SteamId = p.SteamID.ToString(),
Name = p.PlayerName,
IpAddress = p.IpAddress?.Split(":")[0]
};
if (!g_bCommandsAllowed || (LifeState_t)p.LifeState != LifeState_t.LIFE_ALIVE ||
weaponSync == null) return;
RefreshWeapons(player);
try
{
_ = Task.Run(async () => await weaponSync.SyncWeaponPaintsToDatabase(playerInfo));
}
catch (Exception ex)
{
Utility.Log($"Error syncing weapon paints: {ex.Message}");
}
}
};
// Add skin options to the submenu for the selected weapon
if (skinsForSelectedWeapon != null)
{
foreach (var skin in skinsForSelectedWeapon)
{
if (!skin.TryGetValue("paint_name", out var paintNameObj) ||
!skin.TryGetValue("paint", out var paintObj)) continue;
var paintName = paintNameObj?.ToString();
var paint = paintObj?.ToString();
if (!string.IsNullOrEmpty(paintName) && !string.IsNullOrEmpty(paint))
{
skinSubMenu.AddMenuOption($"{paintName} ({paint})", handleSkinSelection);
} }
} }
if (player != null && Utility.IsPlayerValid(player))
MenuManager.OpenChatMenu(player, skinSubMenu);
} }
if (player != null && Utility.IsPlayerValid(player))
MenuManager.OpenChatMenu(player, skinSubMenu);
}; };
// Add weapon options to the weapon selection menu // Add weapon options to the weapon selection menu
foreach (var weaponClass in weaponList.Keys) foreach (var weaponName in WeaponList.Keys.Select(weaponClass => WeaponList[weaponClass]))
{ {
string weaponName = weaponList[weaponClass];
weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection); weaponSelectionMenu.AddMenuOption(weaponName, handleWeaponSelection);
} }
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
@@ -338,8 +329,8 @@ namespace WeaponPaints
if (player == null || player.UserId == null) return; if (player == null || player.UserId == null) return;
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
MenuManager.OpenChatMenu(player, weaponSelectionMenu); MenuManager.OpenChatMenu(player, weaponSelectionMenu);
@@ -354,96 +345,95 @@ namespace WeaponPaints
private void SetupGlovesMenu() private void SetupGlovesMenu()
{ {
var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"]); var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"])
glovesSelectionMenu.PostSelectAction = PostSelectAction.Close; {
PostSelectAction = PostSelectAction.Close
};
var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) => var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) =>
{ {
if (!Utility.IsPlayerValid(player) || player is null) return; if (!Utility.IsPlayerValid(player) || player is null) return;
string selectedPaintName = option.Text; var selectedPaintName = option.Text;
var selectedGlove = glovesList.FirstOrDefault(g => g.ContainsKey("paint_name") && g["paint_name"]?.ToString() == selectedPaintName); var selectedGlove = glovesList.FirstOrDefault(g => g.ContainsKey("paint_name") && g["paint_name"]?.ToString() == selectedPaintName);
if (selectedGlove != null) var image = selectedGlove?["image"]?.ToString() ?? "";
if (
selectedGlove != null &&
selectedGlove.ContainsKey("weapon_defindex") &&
selectedGlove.ContainsKey("paint") &&
int.TryParse(selectedGlove["weapon_defindex"]?.ToString(), out var weaponDefindex) &&
int.TryParse(selectedGlove["paint"]?.ToString(), out var paint)
)
{ {
if ( if (Config.Additional.ShowSkinImage)
selectedGlove != null &&
selectedGlove.ContainsKey("weapon_defindex") &&
selectedGlove.ContainsKey("paint") &&
int.TryParse(selectedGlove["weapon_defindex"]?.ToString(), out int weaponDefindex) &&
int.TryParse(selectedGlove["paint"]?.ToString(), out int paint)
)
{ {
if (Config.Additional.ShowSkinImage) PlayerWeaponImage[player.Slot] = image;
{ AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
string image = selectedGlove["image"]?.ToString() ?? "";
PlayerWeaponImage[player.Slot] = image;
AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
if (paint != 0)
{
g_playersGlove[player.Slot] = (ushort)weaponDefindex;
if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefindex))
{
WeaponInfo weaponInfo = new();
weaponInfo.Paint = paint;
gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo;
}
}
else
{
g_playersGlove.TryRemove(player.Slot, out _);
}
if (!string.IsNullOrEmpty(Localizer["wp_glove_menu_select"]))
{
player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]);
}
if (weaponSync != null)
{
_ = Task.Run(async () =>
{
await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex);
if (!gPlayerWeaponsInfo[playerInfo.Slot].TryGetValue(weaponDefindex, out WeaponInfo? value))
{
value = new WeaponInfo();
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex] = value;
}
value.Paint = paint;
value.Wear = 0.00f;
value.Seed = 0;
await weaponSync.SyncWeaponPaintsToDatabase(playerInfo);
});
}
RefreshGloves(player);
} }
};
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
if (paint != 0)
{
g_playersGlove[player.Slot] = (ushort)weaponDefindex;
if (!gPlayerWeaponsInfo[player.Slot].ContainsKey(weaponDefindex))
{
WeaponInfo weaponInfo = new()
{
Paint = paint
};
gPlayerWeaponsInfo[player.Slot][weaponDefindex] = weaponInfo;
}
}
else
{
g_playersGlove.TryRemove(player.Slot, out _);
}
if (!string.IsNullOrEmpty(Localizer["wp_glove_menu_select"]))
{
player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]);
}
if (weaponSync != null)
{
_ = Task.Run(async () =>
{
await weaponSync.SyncGloveToDatabase(playerInfo, weaponDefindex);
if (!gPlayerWeaponsInfo[playerInfo.Slot].TryGetValue(weaponDefindex, out var value))
{
value = new WeaponInfo();
gPlayerWeaponsInfo[playerInfo.Slot][weaponDefindex] = value;
}
value.Paint = paint;
value.Wear = 0.00f;
value.Seed = 0;
await weaponSync.SyncWeaponPaintsToDatabase(playerInfo);
});
}
RefreshGloves(player);
}
;
}; };
// Add weapon options to the weapon selection menu // Add weapon options to the weapon selection menu
foreach (var gloveObject in glovesList) foreach (var paintName in glovesList.Select(gloveObject => gloveObject["paint_name"]?.ToString() ?? "").Where(paintName => paintName.Length > 0))
{ {
string paintName = gloveObject["paint_name"]?.ToString() ?? ""; glovesSelectionMenu.AddMenuOption(paintName, handleGloveSelection);
if (paintName.Length > 0)
glovesSelectionMenu.AddMenuOption(paintName, handleGloveSelection);
} }
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
@@ -453,8 +443,8 @@ namespace WeaponPaints
if (player == null || player.UserId == null) return; if (player == null || player.UserId == null) return;
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
MenuManager.OpenChatMenu(player, glovesSelectionMenu); MenuManager.OpenChatMenu(player, glovesSelectionMenu);
@@ -473,7 +463,7 @@ namespace WeaponPaints
{ {
if (!Utility.IsPlayerValid(player) || player is null) return; if (!Utility.IsPlayerValid(player) || player is null) return;
string selectedPaintName = option.Text; var selectedPaintName = option.Text;
var selectedAgent = agentsList.FirstOrDefault(g => var selectedAgent = agentsList.FirstOrDefault(g =>
g.ContainsKey("agent_name") && g.ContainsKey("agent_name") &&
g["agent_name"] != null && g["agent_name"]!.ToString() == selectedPaintName && g["agent_name"] != null && g["agent_name"]!.ToString() == selectedPaintName &&
@@ -482,7 +472,6 @@ namespace WeaponPaints
if (selectedAgent == null) return; if (selectedAgent == null) return;
if ( if (
selectedAgent != null &&
selectedAgent.ContainsKey("model") selectedAgent.ContainsKey("model")
) )
{ {
@@ -498,7 +487,7 @@ namespace WeaponPaints
if (Config.Additional.ShowSkinImage) if (Config.Additional.ShowSkinImage)
{ {
string image = selectedAgent["image"]?.ToString() ?? ""; var image = selectedAgent["image"]?.ToString() ?? "";
PlayerWeaponImage[player.Slot] = image; PlayerWeaponImage[player.Slot] = image;
AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
} }
@@ -539,15 +528,17 @@ namespace WeaponPaints
if (player == null || player.UserId == null) return; if (player == null || player.UserId == null) return;
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
var agentsSelectionMenu = new ChatMenu(Localizer["wp_agent_menu_title"]); var agentsSelectionMenu = new ChatMenu(Localizer["wp_agent_menu_title"])
agentsSelectionMenu.PostSelectAction = PostSelectAction.Close; {
PostSelectAction = PostSelectAction.Close
};
var filteredAgents = agentsList.Where(agentObject => var filteredAgents = agentsList.Where(agentObject =>
{ {
if (agentObject["team"]?.Value<int>() is int teamNum) if (agentObject["team"]?.Value<int>() is { } teamNum)
{ {
return teamNum == player.TeamNum; return teamNum == player.TeamNum;
} }
@@ -561,7 +552,7 @@ namespace WeaponPaints
foreach (var agentObject in filteredAgents) foreach (var agentObject in filteredAgents)
{ {
string paintName = agentObject["agent_name"]?.ToString() ?? ""; var paintName = agentObject["agent_name"]?.ToString() ?? "";
if (paintName.Length > 0) if (paintName.Length > 0)
agentsSelectionMenu.AddMenuOption(paintName, handleAgentSelection); agentsSelectionMenu.AddMenuOption(paintName, handleAgentSelection);
@@ -580,66 +571,63 @@ namespace WeaponPaints
private void SetupMusicMenu() private void SetupMusicMenu()
{ {
var musicSelectionMenu = new ChatMenu(Localizer["wp_music_menu_title"]); var musicSelectionMenu = new ChatMenu(Localizer["wp_music_menu_title"])
musicSelectionMenu.PostSelectAction = PostSelectAction.Close; {
PostSelectAction = PostSelectAction.Close
};
var handleMusicSelection = (CCSPlayerController? player, ChatMenuOption option) => var handleMusicSelection = (CCSPlayerController? player, ChatMenuOption option) =>
{ {
if (!Utility.IsPlayerValid(player) || player is null) return; if (!Utility.IsPlayerValid(player) || player is null) return;
string selectedPaintName = option.Text; var selectedPaintName = option.Text;
var selectedMusic = musicList.FirstOrDefault(g => g.ContainsKey("name") && g["name"]?.ToString() == selectedPaintName); var selectedMusic = musicList.FirstOrDefault(g => g.ContainsKey("name") && g["name"]?.ToString() == selectedPaintName);
if (selectedMusic != null) if (selectedMusic != null)
{ {
if ( if (!selectedMusic.ContainsKey("id") ||
selectedMusic != null && !selectedMusic.ContainsKey("name") ||
selectedMusic.ContainsKey("id") && !int.TryParse(selectedMusic["id"]?.ToString(), out var paint)) return;
selectedMusic.ContainsKey("name") && var image = selectedMusic["image"]?.ToString() ?? "";
int.TryParse(selectedMusic["id"]?.ToString(), out int paint) if (Config.Additional.ShowSkinImage)
)
{ {
if (Config.Additional.ShowSkinImage) PlayerWeaponImage[player.Slot] = image;
{ AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
string image = selectedMusic["image"]?.ToString() ?? "";
PlayerWeaponImage[player.Slot] = image;
AddTimer(2.0f, () => PlayerWeaponImage.Remove(player.Slot), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
if (paint != 0)
{
g_playersMusic[player.Slot] = (ushort)paint;
}
else
{
g_playersMusic[player.Slot] = 0;
}
if (!string.IsNullOrEmpty(Localizer["wp_music_menu_select"]))
{
player!.Print(Localizer["wp_music_menu_select", selectedPaintName]);
}
if (weaponSync != null)
{
_ = Task.Run(async () =>
{
await weaponSync.SyncMusicToDatabase(playerInfo, (ushort)paint);
});
}
//RefreshGloves(player);
} }
PlayerInfo playerInfo = new PlayerInfo
{
UserId = player.UserId,
Slot = player.Slot,
Index = (int)player.Index,
SteamId = player.SteamID.ToString(),
Name = player.PlayerName,
IpAddress = player.IpAddress?.Split(":")[0]
};
if (paint != 0)
{
g_playersMusic[player.Slot] = (ushort)paint;
}
else
{
g_playersMusic[player.Slot] = 0;
}
if (!string.IsNullOrEmpty(Localizer["wp_music_menu_select"]))
{
player!.Print(Localizer["wp_music_menu_select", selectedPaintName]);
}
if (weaponSync != null)
{
_ = Task.Run(async () =>
{
await weaponSync.SyncMusicToDatabase(playerInfo, (ushort)paint);
});
}
//RefreshGloves(player);
} }
else else
{ {
@@ -672,12 +660,9 @@ namespace WeaponPaints
musicSelectionMenu.AddMenuOption(Localizer["None"], handleMusicSelection); musicSelectionMenu.AddMenuOption(Localizer["None"], handleMusicSelection);
// Add weapon options to the weapon selection menu // Add weapon options to the weapon selection menu
foreach (var musicObject in musicList) foreach (var paintName in musicList.Select(musicObject => musicObject["name"]?.ToString() ?? "").Where(paintName => paintName.Length > 0))
{ {
string paintName = musicObject["name"]?.ToString() ?? ""; musicSelectionMenu.AddMenuOption(paintName, handleMusicSelection);
if (paintName.Length > 0)
musicSelectionMenu.AddMenuOption(paintName, handleMusicSelection);
} }
// Command to open the weapon selection menu for players // Command to open the weapon selection menu for players
@@ -687,8 +672,8 @@ namespace WeaponPaints
if (player == null || player.UserId == null) return; if (player == null || player.UserId == null) return;
if (player != null && !commandsCooldown.TryGetValue(player.Slot, out DateTime cooldownEndTime) || if (!commandsCooldown.TryGetValue(player.Slot, out var cooldownEndTime) ||
player != null && DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) DateTime.UtcNow >= (commandsCooldown.TryGetValue(player.Slot, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow))
{ {
commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); commandsCooldown[player.Slot] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds);
MenuManager.OpenChatMenu(player, musicSelectionMenu); MenuManager.OpenChatMenu(player, musicSelectionMenu);

View File

@@ -89,6 +89,6 @@ namespace WeaponPaints
public string Website { get; set; } = "example.com/skins"; public string Website { get; set; } = "example.com/skins";
[JsonPropertyName("Additional")] [JsonPropertyName("Additional")]
public Additional Additional { get; set; } = new Additional(); public Additional Additional { get; set; } = new();
} }
} }

View File

@@ -18,7 +18,7 @@ namespace WeaponPaints
if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17 || if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17 ||
weaponSync == null || _database == null) return HookResult.Continue; weaponSync == null || _database == null) return HookResult.Continue;
PlayerInfo playerInfo = new PlayerInfo PlayerInfo? playerInfo = new PlayerInfo
{ {
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
@@ -54,7 +54,7 @@ namespace WeaponPaints
} }
*/ */
} }
catch (Exception) catch
{ {
} }
@@ -108,7 +108,7 @@ namespace WeaponPaints
private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon) private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon weapon)
{ {
if (!Config.Additional.SkinEnabled) return; if (!Config.Additional.SkinEnabled) return;
if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out System.Collections.Concurrent.ConcurrentDictionary<int, WeaponInfo>? _value)) return; if (!gPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return;
bool isKnife = weapon.DesignerName.Contains("knife") || weapon.DesignerName.Contains("bayonet"); bool isKnife = weapon.DesignerName.Contains("knife") || weapon.DesignerName.Contains("bayonet");
@@ -143,31 +143,23 @@ namespace WeaponPaints
weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex); weapon.FallbackPaintKit = GetRandomPaint(weaponDefIndex);
weapon.FallbackSeed = 0; weapon.FallbackSeed = 0;
weapon.FallbackWear = 0.000001f; weapon.FallbackWear = 0.000001f;
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit); CAttributeListSetOrAddAttributeValueByName.Invoke(
weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab",
weapon.FallbackPaintKit);
fallbackPaintKit = weapon.FallbackPaintKit; fallbackPaintKit = weapon.FallbackPaintKit;
if (fallbackPaintKit == 0) if (fallbackPaintKit == 0)
return; return;
if (!isKnife) if (isKnife) return;
{ UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit));
if (newPaints.Contains(fallbackPaintKit))
{
UpdatePlayerWeaponMeshGroupMask(player, weapon, false);
}
else
{
UpdatePlayerWeaponMeshGroupMask(player, weapon, true);
}
}
return; return;
} }
if (!gPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefIndex, out WeaponInfo? value) || value.Paint == 0) return; if (!gPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefIndex, out var value) || value.Paint == 0) return;
WeaponInfo weaponInfo = value; var weaponInfo = value;
//Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}"); //Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
weapon.AttributeManager.Item.ItemID = 16384; weapon.AttributeManager.Item.ItemID = 16384;
weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF; weapon.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
@@ -175,29 +167,20 @@ namespace WeaponPaints
weapon.FallbackPaintKit = weaponInfo.Paint; weapon.FallbackPaintKit = weaponInfo.Paint;
weapon.FallbackSeed = weaponInfo.Seed; weapon.FallbackSeed = weaponInfo.Seed;
weapon.FallbackWear = weaponInfo.Wear; weapon.FallbackWear = weaponInfo.Wear;
CAttributeList_SetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit); CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
fallbackPaintKit = weapon.FallbackPaintKit; fallbackPaintKit = weapon.FallbackPaintKit;
if (fallbackPaintKit == 0) if (fallbackPaintKit == 0)
return; return;
if (!isKnife) if (isKnife) return;
{ UpdatePlayerWeaponMeshGroupMask(player, weapon, !newPaints.Contains(fallbackPaintKit));
if (newPaints.Contains(fallbackPaintKit))
{
UpdatePlayerWeaponMeshGroupMask(player, weapon, false);
}
else
{
UpdatePlayerWeaponMeshGroupMask(player, weapon, true);
}
}
} }
private void OnMapStart(string mapName) private void OnMapStart(string mapName)
{ {
if (!Config.Additional.KnifeEnabled && !Config.Additional.SkinEnabled && !Config.Additional.GloveEnabled) return; if (Config.Additional is { KnifeEnabled: false, SkinEnabled: false, GloveEnabled: false }) return;
if (_database != null) if (_database != null)
weaponSync = new WeaponSynchronization(_database, Config); weaponSync = new WeaponSynchronization(_database, Config);
@@ -207,7 +190,7 @@ namespace WeaponPaints
{ {
CCSPlayerController? player = @event.Userid; CCSPlayerController? player = @event.Userid;
if (player is null || !player.IsValid || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled) if (player is null || !player.IsValid || Config.Additional is { KnifeEnabled: false, GloveEnabled: false })
return HookResult.Continue; return HookResult.Continue;
CCSPlayerPawn? pawn = player.PlayerPawn.Value; CCSPlayerPawn? pawn = player.PlayerPawn.Value;
@@ -237,17 +220,10 @@ namespace WeaponPaints
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{ {
/*
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
NativeAPI.IssueServerCommand("mp_equipment_reset_rounds 0");
*/
g_bCommandsAllowed = true; g_bCommandsAllowed = true;
return HookResult.Continue; return HookResult.Continue;
} }
public HookResult OnGiveNamedItemPost(DynamicHook hook) public HookResult OnGiveNamedItemPost(DynamicHook hook)
{ {
try try
@@ -266,7 +242,6 @@ namespace WeaponPaints
return HookResult.Continue; return HookResult.Continue;
} }
public void OnEntityCreated(CEntityInstance entity) public void OnEntityCreated(CEntityInstance entity)
{ {
var designerName = entity.DesignerName; var designerName = entity.DesignerName;
@@ -276,7 +251,7 @@ namespace WeaponPaints
Server.NextFrame(() => Server.NextFrame(() =>
{ {
var weapon = new CBasePlayerWeapon(entity.Handle); var weapon = new CBasePlayerWeapon(entity.Handle);
if (weapon == null || !weapon.IsValid) return; if (!weapon.IsValid) return;
try try
{ {
@@ -289,7 +264,7 @@ namespace WeaponPaints
if (_steamid != null && _steamid.IsValid()) if (_steamid != null && _steamid.IsValid())
{ {
player = Utilities.GetPlayers().Where(p => p is not null && p.IsValid && p.SteamID == _steamid.SteamId64).FirstOrDefault(); player = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.SteamID == _steamid.SteamId64);
if (player == null) if (player == null)
player = Utilities.GetPlayerFromSteamId(weapon.OriginalOwnerXuidLow); player = Utilities.GetPlayerFromSteamId(weapon.OriginalOwnerXuidLow);
@@ -301,7 +276,7 @@ namespace WeaponPaints
} }
if (string.IsNullOrEmpty(player?.PlayerName)) return; if (string.IsNullOrEmpty(player?.PlayerName)) return;
if (player is null || !Utility.IsPlayerValid(player)) return; if (!Utility.IsPlayerValid(player)) return;
GivePlayerWeaponSkin(player, weapon); GivePlayerWeaponSkin(player, weapon);
} }
@@ -318,13 +293,13 @@ namespace WeaponPaints
if (!Config.Additional.ShowSkinImage) return; if (!Config.Additional.ShowSkinImage) return;
foreach (var player in Utilities.GetPlayers().Where(p => foreach (var player in Utilities.GetPlayers().Where(p =>
p is not null && p.IsValid && p.PlayerPawn != null && p.PlayerPawn.IsValid && p is { IsValid: true, PlayerPawn.IsValid: true } &&
(LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && p.SteamID.ToString().Length == 17 (LifeState_t)p.LifeState == LifeState_t.LIFE_ALIVE && p.SteamID.ToString().Length == 17
&& !p.IsBot && !p.IsHLTV && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsBot && p is { IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected }
) )
) )
{ {
if (PlayerWeaponImage.TryGetValue(player.Slot, out string? value) && !string.IsNullOrEmpty(value)) if (PlayerWeaponImage.TryGetValue(player.Slot, out var value) && !string.IsNullOrEmpty(value))
{ {
player.PrintToCenterHtml("<img src='{PATH}'</img>".Replace("{PATH}", value)); player.PrintToCenterHtml("<img src='{PATH}'</img>".Replace("{PATH}", value));
} }

View File

@@ -3,9 +3,9 @@
public class PlayerInfo public class PlayerInfo
{ {
public int Index { get; set; } public int Index { get; set; }
public int Slot { get; set; } public int Slot { get; init; }
public int? UserId { get; set; } public int? UserId { get; set; }
public string? SteamId { get; set; } public string? SteamId { get; init; }
public string? Name { get; set; } public string? Name { get; set; }
public string? IpAddress { get; set; } public string? IpAddress { get; set; }
} }

View File

@@ -25,34 +25,42 @@ namespace WeaponPaints
{ {
string[] createTableQueries = string[] createTableQueries =
[ [
@"CREATE TABLE IF NOT EXISTS `wp_player_skins` ( """
`steamid` varchar(18) NOT NULL, CREATE TABLE IF NOT EXISTS `wp_player_skins` (
`weapon_defindex` int(6) NOT NULL, `steamid` varchar(18) NOT NULL,
`weapon_paint_id` int(6) NOT NULL, `weapon_defindex` int(6) NOT NULL,
`weapon_wear` float NOT NULL DEFAULT 0.000001, `weapon_paint_id` int(6) NOT NULL,
`weapon_seed` int(16) NOT NULL DEFAULT 0 `weapon_wear` float NOT NULL DEFAULT 0.000001,
) ENGINE=InnoDB", `weapon_seed` int(16) NOT NULL DEFAULT 0
) ENGINE=InnoDB
""",
@"CREATE TABLE IF NOT EXISTS `wp_player_knife` ( @"CREATE TABLE IF NOT EXISTS `wp_player_knife` (
`steamid` varchar(18) NOT NULL, `steamid` varchar(18) NOT NULL,
`knife` varchar(64) NOT NULL, `knife` varchar(64) NOT NULL,
UNIQUE (`steamid`) UNIQUE (`steamid`)
) ENGINE = InnoDB", ) ENGINE = InnoDB",
@"CREATE TABLE IF NOT EXISTS `wp_player_gloves` ( """
`steamid` varchar(18) NOT NULL, CREATE TABLE IF NOT EXISTS `wp_player_gloves` (
`weapon_defindex` int(11) NOT NULL, `steamid` varchar(18) NOT NULL,
UNIQUE (`steamid`) `weapon_defindex` int(11) NOT NULL,
) ENGINE=InnoDB", UNIQUE (`steamid`)
@"CREATE TABLE IF NOT EXISTS `wp_player_agents` ( ) ENGINE=InnoDB
`steamid` varchar(18) NOT NULL, """,
`agent_ct` varchar(64) DEFAULT NULL, """
`agent_t` varchar(64) DEFAULT NULL, CREATE TABLE IF NOT EXISTS `wp_player_agents` (
UNIQUE (`steamid`) `steamid` varchar(18) NOT NULL,
) ENGINE=InnoDB", `agent_ct` varchar(64) DEFAULT NULL,
@"CREATE TABLE IF NOT EXISTS `wp_player_music` ( `agent_t` varchar(64) DEFAULT NULL,
`steamid` varchar(64) NOT NULL, UNIQUE (`steamid`)
`music_id` int(11) NOT NULL, ) ENGINE=InnoDB
UNIQUE (`steamid`) """,
) ENGINE=InnoDB", """
CREATE TABLE IF NOT EXISTS `wp_player_music` (
`steamid` varchar(64) NOT NULL,
`music_id` int(11) NOT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
]; ];
foreach (var query in createTableQueries) foreach (var query in createTableQueries)
@@ -78,16 +86,16 @@ namespace WeaponPaints
{ {
if (player is null || WeaponPaints.weaponSync is null) return false; if (player is null || WeaponPaints.weaponSync is null) return false;
return (player.IsValid && !player.IsBot && !player.IsHLTV && player.UserId.HasValue); return player is { IsValid: true, IsBot: false, IsHLTV: false, UserId: not null };
} }
internal static void LoadSkinsFromFile(string filePath, ILogger logger) internal static void LoadSkinsFromFile(string filePath, ILogger logger)
{ {
string json = File.ReadAllText(filePath);
try try
{ {
string json = File.ReadAllText(filePath);
var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json); var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json);
WeaponPaints.skinsList = deserializedSkins ?? new List<JObject>(); WeaponPaints.skinsList = deserializedSkins ?? [];
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -99,9 +107,9 @@ namespace WeaponPaints
{ {
try try
{ {
string json = File.ReadAllText(filePath); var json = File.ReadAllText(filePath);
var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json); var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json);
WeaponPaints.glovesList = deserializedSkins ?? new List<JObject>(); WeaponPaints.glovesList = deserializedSkins ?? [];
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -113,9 +121,9 @@ namespace WeaponPaints
{ {
try try
{ {
string json = File.ReadAllText(filePath); var json = File.ReadAllText(filePath);
var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json); var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json);
WeaponPaints.agentsList = deserializedSkins ?? new List<JObject>(); WeaponPaints.agentsList = deserializedSkins ?? [];
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -127,9 +135,9 @@ namespace WeaponPaints
{ {
try try
{ {
string json = File.ReadAllText(filePath); var json = File.ReadAllText(filePath);
var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json); var deserializedSkins = JsonConvert.DeserializeObject<List<JObject>>(json);
WeaponPaints.musicList = deserializedSkins ?? new List<JObject>(); WeaponPaints.musicList = deserializedSkins ?? [];
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -156,26 +164,26 @@ namespace WeaponPaints
try try
{ {
HttpResponseMessage response = await client.GetAsync("https://raw.githubusercontent.com/Nereziel/cs2-WeaponPaints/main/VERSION").ConfigureAwait(false); var response = await client.GetAsync("https://raw.githubusercontent.com/Nereziel/cs2-WeaponPaints/main/VERSION").ConfigureAwait(false);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
string remoteVersion = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var remoteVersion = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
remoteVersion = remoteVersion.Trim(); remoteVersion = remoteVersion.Trim();
int comparisonResult = string.Compare(version, remoteVersion); var comparisonResult = string.CompareOrdinal(version, remoteVersion);
if (comparisonResult < 0) switch (comparisonResult)
{ {
logger.LogWarning("Plugin is outdated! Check https://github.com/Nereziel/cs2-WeaponPaints"); case < 0:
} logger.LogWarning("Plugin is outdated! Check https://github.com/Nereziel/cs2-WeaponPaints");
else if (comparisonResult > 0) break;
{ case > 0:
logger.LogInformation("Probably dev version detected"); logger.LogInformation("Probably dev version detected");
} break;
else default:
{ logger.LogInformation("Plugin is up to date");
logger.LogInformation("Plugin is up to date"); break;
} }
} }
else else

View File

@@ -1 +1 @@
2.4d 2.4e

View File

@@ -11,7 +11,7 @@ namespace WeaponPaints
{ {
public partial class WeaponPaints public partial class WeaponPaints
{ {
internal static void GiveKnifeToPlayer(CCSPlayerController? player) private static void GiveKnifeToPlayer(CCSPlayerController? player)
{ {
if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return; if (!_config.Additional.KnifeEnabled || player == null || !player.IsValid) return;
@@ -21,11 +21,11 @@ namespace WeaponPaints
player.GiveNamedItem(CsItem.Knife); player.GiveNamedItem(CsItem.Knife);
} }
internal static bool PlayerHasKnife(CCSPlayerController? player) private static bool PlayerHasKnife(CCSPlayerController? player)
{ {
if (!_config.Additional.KnifeEnabled) return false; if (!_config.Additional.KnifeEnabled) return false;
if (player == null || !player.IsValid || player.PlayerPawn == null || !player.PlayerPawn.IsValid) if (player == null || !player.IsValid || !player.PlayerPawn.IsValid)
{ {
return false; return false;
} }
@@ -37,18 +37,16 @@ namespace WeaponPaints
if (weapons == null) return false; if (weapons == null) return false;
foreach (var weapon in weapons) foreach (var weapon in weapons)
{ {
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) if (!weapon.IsValid || weapon.Value == null || !weapon.Value.IsValid) continue;
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet"))
{ {
if (weapon.Value.DesignerName.Contains("knife") || weapon.Value.DesignerName.Contains("bayonet")) return true;
{
return true;
}
} }
} }
return false; return false;
} }
internal void RefreshWeapons(CCSPlayerController? player) private void RefreshWeapons(CCSPlayerController? player)
{ {
if (!g_bCommandsAllowed) return; if (!g_bCommandsAllowed) return;
if (player == null || !player.IsValid || player.PlayerPawn?.Value == null || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE) if (player == null || !player.IsValid || player.PlayerPawn?.Value == null || (LifeState_t)player.LifeState != LifeState_t.LIFE_ALIVE)
@@ -58,9 +56,9 @@ namespace WeaponPaints
var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons; var weapons = player.PlayerPawn.Value.WeaponServices.MyWeapons;
if (weapons == null || weapons.Count == 0) if (weapons.Count == 0)
return; return;
if (player.Team == CsTeam.None || player.Team == CsTeam.Spectator) if (player.Team is CsTeam.None or CsTeam.Spectator)
return; return;
int playerTeam = player.TeamNum; int playerTeam = player.TeamNum;
@@ -69,37 +67,33 @@ namespace WeaponPaints
foreach (var weapon in weapons) foreach (var weapon in weapons)
{ {
if (weapon == null || !weapon.IsValid || weapon.Value == null || if (!weapon.IsValid || weapon.Value == null ||
!weapon.Value.IsValid || !weapon.Value.DesignerName.Contains("weapon_")) !weapon.Value.IsValid || !weapon.Value.DesignerName.Contains("weapon_"))
continue; continue;
CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>(); CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>();
if (weapon.Value.Entity == null) continue; if (weapon.Value.Entity == null) continue;
if (weapon.Value.OwnerEntity == null) continue;
if (!weapon.Value.OwnerEntity.IsValid) continue; if (!weapon.Value.OwnerEntity.IsValid) continue;
if (gun == null) continue;
if (gun.Entity == null) continue; if (gun.Entity == null) continue;
if (!gun.IsValid) continue; if (!gun.IsValid) continue;
if (!gun.VisibleinPVS) continue; if (!gun.VisibleinPVS) continue;
try try
{ {
string? weaponByDefindex = null;
CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData; CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
if (weaponData == null) continue; if (weaponData == null) continue;
if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_RIFLE || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_PISTOL) if (weaponData.GearSlot == gear_slot_t.GEAR_SLOT_RIFLE || weaponData.GearSlot == gear_slot_t.GEAR_SLOT_PISTOL)
{ {
if (!WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, out weaponByDefindex)) if (!WeaponDefindex.TryGetValue(weapon.Value.AttributeManager.Item.ItemDefinitionIndex, out var weaponByDefindex))
continue; continue;
int clip1 = weapon.Value.Clip1; int clip1 = weapon.Value.Clip1;
int reservedAmmo = weapon.Value.ReserveAmmo[0]; int reservedAmmo = weapon.Value.ReserveAmmo[0];
if (!weaponsWithAmmo.TryGetValue(weaponByDefindex, out List<(int, int)>? value)) if (!weaponsWithAmmo.TryGetValue(weaponByDefindex, out var value))
{ {
value = []; value = [];
weaponsWithAmmo.Add(weaponByDefindex, value); weaponsWithAmmo.Add(weaponByDefindex, value);
@@ -107,7 +101,7 @@ namespace WeaponPaints
value.Add((clip1, reservedAmmo)); value.Add((clip1, reservedAmmo));
if (gun == null || gun.VData == null) return; if (gun.VData == null) return;
weapon.Value.Remove(); weapon.Value.Remove();
} }
@@ -121,16 +115,16 @@ namespace WeaponPaints
try try
{ {
player.ExecuteClientCommandFromServer("slot 3"); player.ExecuteClientCommand("slot 3");
player.ExecuteClientCommandFromServer("slot 3"); player.ExecuteClientCommand("slot 3");
var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon; var weapon = player.PlayerPawn.Value.WeaponServices.ActiveWeapon;
if (weapon is null || !weapon.IsValid || weapon.Value == null) return; if (!weapon.IsValid || weapon.Value == null) return;
CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData; CCSWeaponBaseVData? weaponData = weapon.Value.As<CCSWeaponBase>().VData;
if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE) if (weapon.Value.DesignerName.Contains("knife") || weaponData?.GearSlot == gear_slot_t.GEAR_SLOT_KNIFE)
{ {
CCSWeaponBaseGun gun = weapon.Value.As<CCSWeaponBaseGun>(); CCSWeaponBaseGun gun;
AddTimer(0.3f, () => AddTimer(0.3f, () =>
{ {
@@ -144,7 +138,7 @@ namespace WeaponPaints
{ {
if (player.TeamNum != playerTeam) return; if (player.TeamNum != playerTeam) return;
if (gun == null || !gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return; if (!gun.IsValid || gun.State != CSWeaponState_t.WEAPON_NOT_CARRIED) return;
gun.Remove(); gun.Remove();
}); });
@@ -171,11 +165,8 @@ namespace WeaponPaints
{ {
try try
{ {
if (newWeapon != null) newWeapon.Clip1 = ammo.Item1;
{ newWeapon.ReserveAmmo[0] = ammo.Item2;
newWeapon.Clip1 = ammo.Item1;
newWeapon.ReserveAmmo[0] = ammo.Item2;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -195,7 +186,7 @@ namespace WeaponPaints
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
return; return;
string model = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance()?.ModelState.ModelName ?? string.Empty; var model = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance()?.ModelState.ModelName ?? string.Empty;
if (!string.IsNullOrEmpty(model)) if (!string.IsNullOrEmpty(model))
{ {
pawn.SetModel("characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl"); pawn.SetModel("characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl");
@@ -204,35 +195,30 @@ namespace WeaponPaints
Instance.AddTimer(0.06f, () => Instance.AddTimer(0.06f, () =>
{ {
CEconItemView item = pawn.EconGloves;
try try
{ {
if (player == null || !player.IsValid) if (!player.IsValid)
return; return;
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) if (!player.PawnIsAlive)
return; return;
if (g_playersGlove.TryGetValue(player.Slot, out var gloveInfo) && gloveInfo != 0) if (!g_playersGlove.TryGetValue(player.Slot, out var gloveInfo) || gloveInfo == 0) return;
{
CCSPlayerPawn? pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
return;
WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][gloveInfo]; WeaponInfo weaponInfo = gPlayerWeaponsInfo[player.Slot][gloveInfo];
CEconItemView item = pawn.EconGloves; item.ItemDefinitionIndex = gloveInfo;
item.ItemDefinitionIndex = gloveInfo; item.ItemIDLow = 16384 & 0xFFFFFFFF;
item.ItemIDLow = 16384 & 0xFFFFFFFF; item.ItemIDHigh = 16384;
item.ItemIDHigh = 16384;
CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weaponInfo.Paint); CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weaponInfo.Paint);
CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture seed", weaponInfo.Seed); CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture seed", weaponInfo.Seed);
CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture wear", weaponInfo.Wear); CAttributeListSetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture wear", weaponInfo.Wear);
item.Initialized = true; item.Initialized = true;
CBaseModelEntity_SetBodygroup.Invoke(pawn, "default_gloves", 1); CBaseModelEntitySetBodygroup.Invoke(pawn, "default_gloves", 1);
}
} }
catch (Exception) { } catch (Exception) { }
}, TimerFlags.STOP_ON_MAPCHANGE); }, TimerFlags.STOP_ON_MAPCHANGE);
@@ -240,7 +226,7 @@ namespace WeaponPaints
private static int GetRandomPaint(int defindex) private static int GetRandomPaint(int defindex)
{ {
if (skinsList == null || skinsList.Count == 0) if (skinsList.Count == 0)
return 0; return 0;
Random rnd = new Random(); Random rnd = new Random();
@@ -253,55 +239,46 @@ namespace WeaponPaints
var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)]; var randomWeapon = filteredWeapons[rnd.Next(filteredWeapons.Count)];
if (int.TryParse(randomWeapon["paint"]?.ToString(), out int paintValue)) return int.TryParse(randomWeapon["paint"]?.ToString(), out var paintValue) ? paintValue : 0;
return paintValue;
return 0;
} }
public static void SubclassChange(CBasePlayerWeapon weapon, ushort itemD) private static void SubclassChange(CBasePlayerWeapon weapon, ushort itemD)
{ {
var SubclassChangeFunc = VirtualFunction.Create<nint, string, int>( var subclassChangeFunc = VirtualFunction.Create<nint, string, int>(
GameData.GetSignature("ChangeSubclass") GameData.GetSignature("ChangeSubclass")
); );
SubclassChangeFunc(weapon.Handle, itemD.ToString()); subclassChangeFunc(weapon.Handle, itemD.ToString());
} }
public static void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false) private static void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false)
{ {
if (weapon.CBodyComponent != null && weapon.CBodyComponent.SceneNode != null) if (weapon.CBodyComponent?.SceneNode == null) return;
{ var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance();
var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance(); var value = (ulong)(isLegacy ? 2 : 1);
if (skeleton != null)
{
var value = (ulong)(isLegacy ? 2 : 1);
if (skeleton.ModelState.MeshGroupMask != value) if (skeleton.ModelState.MeshGroupMask != value)
{ {
skeleton.ModelState.MeshGroupMask = value; skeleton.ModelState.MeshGroupMask = value;
}
}
} }
} }
public static void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy) private static void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy)
{ {
UpdateWeaponMeshGroupMask(weapon, isLegacy); UpdateWeaponMeshGroupMask(weapon, isLegacy);
var viewModel = GetPlayerViewModel(player); var viewModel = GetPlayerViewModel(player);
if (viewModel != null && viewModel.Weapon.Value != null && viewModel.Weapon.Value.Index == weapon.Index) if (viewModel == null || viewModel.Weapon.Value == null ||
{ viewModel.Weapon.Value.Index != weapon.Index) return;
UpdateWeaponMeshGroupMask(viewModel, isLegacy); UpdateWeaponMeshGroupMask(viewModel, isLegacy);
Utilities.SetStateChanged(viewModel, "CBaseEntity", "m_CBodyComponent"); Utilities.SetStateChanged(viewModel, "CBaseEntity", "m_CBodyComponent");
}
} }
public static void GivePlayerAgent(CCSPlayerController player) private static void GivePlayerAgent(CCSPlayerController player)
{ {
if (!g_playersAgent.ContainsKey(player.Slot)) return; if (!g_playersAgent.TryGetValue(player.Slot, out var value)) return;
string? model = player.TeamNum == 3 ? g_playersAgent[player.Slot].CT : g_playersAgent[player.Slot].T; var model = player.TeamNum == 3 ? value.CT : value.T;
if (string.IsNullOrEmpty(model)) return; if (string.IsNullOrEmpty(model)) return;
if (player.PlayerPawn.Value == null) if (player.PlayerPawn.Value == null)
@@ -321,43 +298,41 @@ namespace WeaponPaints
} }
} }
public static void GivePlayerMusicKit(CCSPlayerController player) private static void GivePlayerMusicKit(CCSPlayerController player)
{ {
if (!g_playersMusic.ContainsKey(player.Slot)) return; if (!g_playersMusic.TryGetValue(player.Slot, out var value)) return;
if (player.InventoryServices == null) return; if (player.InventoryServices == null) return;
Console.WriteLine(g_playersMusic[player.Slot]); Console.WriteLine(value);
player.InventoryServices.MusicID = g_playersMusic[player.Slot]; player.InventoryServices.MusicID = value;
} }
public static CCSPlayerController? GetPlayerFromItemServices(CCSPlayer_ItemServices itemServices) private static CCSPlayerController? GetPlayerFromItemServices(CCSPlayer_ItemServices itemServices)
{ {
var pawn = itemServices.Pawn.Value; var pawn = itemServices.Pawn.Value;
if (pawn == null || !pawn.IsValid || !pawn.Controller.IsValid || pawn.Controller.Value == null) return null; if (!pawn.IsValid || !pawn.Controller.IsValid || pawn.Controller.Value == null) return null;
var player = new CCSPlayerController(pawn.Controller.Value.Handle); var player = new CCSPlayerController(pawn.Controller.Value.Handle);
if (!Utility.IsPlayerValid(player)) return null; return !Utility.IsPlayerValid(player) ? null : player;
return player;
} }
private static unsafe CBaseViewModel? GetPlayerViewModel(CCSPlayerController player) private static unsafe CBaseViewModel? GetPlayerViewModel(CCSPlayerController player)
{ {
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null; if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null;
CCSPlayer_ViewModelServices viewModelServices = new(player.PlayerPawn.Value.ViewModelServices!.Handle); CCSPlayer_ViewModelServices viewModelServices = new(player.PlayerPawn.Value.ViewModelServices!.Handle);
nint ptr = viewModelServices.Handle + Schema.GetSchemaOffset("CCSPlayer_ViewModelServices", "m_hViewModel"); var ptr = viewModelServices.Handle + Schema.GetSchemaOffset("CCSPlayer_ViewModelServices", "m_hViewModel");
var references = MemoryMarshal.CreateSpan(ref ptr, 3); var references = MemoryMarshal.CreateSpan(ref ptr, 3);
var viewModel = (CHandle<CBaseViewModel>)Activator.CreateInstance(typeof(CHandle<CBaseViewModel>), references[0])!; var viewModel = (CHandle<CBaseViewModel>)Activator.CreateInstance(typeof(CHandle<CBaseViewModel>), references[0])!;
if (viewModel == null || viewModel.Value == null) return null; return viewModel.Value == null ? null : viewModel.Value;
return viewModel.Value;
} }
public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel> public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel>
{ {
nint ptr = pointer + Schema.GetSchemaOffset(@class, member); var ptr = pointer + Schema.GetSchemaOffset(@class, member);
Span<nint> references = MemoryMarshal.CreateSpan(ref ptr, length); var references = MemoryMarshal.CreateSpan(ref ptr, length);
T[] values = new T[length]; var values = new T[length];
for (int i = 0; i < length; i++) for (var i = 0; i < length; i++)
{ {
values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!; values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!;
} }

View File

@@ -15,7 +15,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
{ {
internal static WeaponPaints Instance { get; private set; } = new(); internal static WeaponPaints Instance { get; private set; } = new();
internal static readonly Dictionary<string, string> weaponList = new() private static readonly Dictionary<string, string> WeaponList = new()
{ {
{"weapon_deagle", "Desert Eagle"}, {"weapon_deagle", "Desert Eagle"},
{"weapon_elite", "Dual Berettas"}, {"weapon_elite", "Dual Berettas"},
@@ -75,9 +75,9 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
{ "weapon_knife_kukri", "Kukri Knife" } { "weapon_knife_kukri", "Kukri Knife" }
}; };
internal static WeaponPaintsConfig _config = new(); private static WeaponPaintsConfig _config = new();
internal static IStringLocalizer? _localizer; internal static IStringLocalizer? _localizer;
internal static Dictionary<int, int> g_knifePickupCount = new(); private static Dictionary<int, int> g_knifePickupCount = new();
internal static ConcurrentDictionary<int, string> g_playersKnife = new(); internal static ConcurrentDictionary<int, string> g_playersKnife = new();
internal static ConcurrentDictionary<int, ushort> g_playersGlove = new(); internal static ConcurrentDictionary<int, ushort> g_playersGlove = new();
internal static ConcurrentDictionary<int, ushort> g_playersMusic = new(); internal static ConcurrentDictionary<int, ushort> g_playersMusic = new();
@@ -88,16 +88,18 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
internal static List<JObject> agentsList = new(); internal static List<JObject> agentsList = new();
internal static List<JObject> musicList = new(); internal static List<JObject> musicList = new();
internal static WeaponSynchronization? weaponSync; internal static WeaponSynchronization? weaponSync;
public static bool g_bCommandsAllowed = true; private static bool g_bCommandsAllowed = true;
internal Dictionary<int, string> PlayerWeaponImage = new(); private Dictionary<int, string> PlayerWeaponImage = new();
internal static Dictionary<int, DateTime> commandsCooldown = new(); private static Dictionary<int, DateTime> commandsCooldown = new();
internal static Database? _database; internal static Database? _database;
internal static MemoryFunctionVoid<nint, string, float> CAttributeList_SetOrAddAttributeValueByName = new(GameData.GetSignature("CAttributeList_SetOrAddAttributeValueByName")); private static readonly MemoryFunctionVoid<nint, string, float> CAttributeListSetOrAddAttributeValueByName = new(GameData.GetSignature("CAttributeList_SetOrAddAttributeValueByName"));
internal static MemoryFunctionVoid<CBaseModelEntity, string, UInt64> CBaseModelEntity_SetBodygroup = new(GameData.GetSignature("CBaseModelEntity_SetBodygroup"));
public static Dictionary<int, string> WeaponDefindex { get; } = new Dictionary<int, string> private static readonly MemoryFunctionVoid<CBaseModelEntity, string, ulong> CBaseModelEntitySetBodygroup =
new(GameData.GetSignature("CBaseModelEntity_SetBodygroup"));
private static Dictionary<int, string> WeaponDefindex { get; } = new Dictionary<int, string>
{ {
{ 1, "weapon_deagle" }, { 1, "weapon_deagle" },
{ 2, "weapon_elite" }, { 2, "weapon_elite" },
@@ -160,7 +162,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
public override string ModuleAuthor => "Nereziel & daffyy"; public override string ModuleAuthor => "Nereziel & daffyy";
public override string ModuleDescription => "Skin, gloves, agents and knife selector, standalone and web-based"; public override string ModuleDescription => "Skin, gloves, agents and knife selector, standalone and web-based";
public override string ModuleName => "WeaponPaints"; public override string ModuleName => "WeaponPaints";
public override string ModuleVersion => "2.4d"; public override string ModuleVersion => "2.4e";
public static WeaponPaintsConfig GetWeaponPaintsConfig() public static WeaponPaintsConfig GetWeaponPaintsConfig()
{ {
@@ -175,22 +177,15 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
{ {
OnMapStart(string.Empty); OnMapStart(string.Empty);
foreach (var player in Utilities.GetPlayers()) foreach (var player in Enumerable.OfType<CCSPlayerController>(Utilities.GetPlayers().TakeWhile(player => weaponSync != null)).Where(player => player.IsValid && player.SteamID.ToString().Length == 17 && !string.IsNullOrEmpty(player.IpAddress) && player is { IsBot: false, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected }))
{ {
if (weaponSync == null)
break;
if (player is null || !player.IsValid || player.SteamID.ToString().Length != 17 || string.IsNullOrEmpty(player.IpAddress) || player.IsBot ||
player.IsHLTV || player.Connected != PlayerConnectedState.PlayerConnected)
continue;
g_knifePickupCount[player.Slot] = 0; g_knifePickupCount[player.Slot] = 0;
gPlayerWeaponsInfo.TryRemove(player.Slot, out _); gPlayerWeaponsInfo.TryRemove(player.Slot, out _);
g_playersKnife.TryRemove(player.Slot, out _); g_playersKnife.TryRemove(player.Slot, out _);
g_playersGlove.TryRemove(player.Slot, out _); g_playersGlove.TryRemove(player.Slot, out _);
g_playersAgent.TryRemove(player.Slot, out _); g_playersAgent.TryRemove(player.Slot, out _);
PlayerInfo playerInfo = new PlayerInfo PlayerInfo? playerInfo = new PlayerInfo
{ {
UserId = player.UserId, UserId = player.UserId,
Slot = player.Slot, Slot = player.Slot,
@@ -200,30 +195,10 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
IpAddress = player?.IpAddress?.Split(":")[0] IpAddress = player?.IpAddress?.Split(":")[0]
}; };
_ = Task.Run(async () => await weaponSync.GetPlayerData(playerInfo)); _ = Task.Run(async () =>
/*
if (Config.Additional.SkinEnabled)
{ {
_ = Task.Run(async () => await weaponSync.GetWeaponPaintsFromDatabase(playerInfo)); if (weaponSync != null) await weaponSync.GetPlayerData(playerInfo);
} });
if (Config.Additional.KnifeEnabled)
{
_ = Task.Run(async () => await weaponSync.GetKnifeFromDatabase(playerInfo));
}
if (Config.Additional.GloveEnabled)
{
_ = Task.Run(async () => await weaponSync.GetGloveFromDatabase(playerInfo));
}
if (Config.Additional.AgentEnabled)
{
_ = Task.Run(async () => await weaponSync.GetAgentFromDatabase(playerInfo));
}
if (Config.Additional.MusicEnabled)
{
_ = Task.Run(async () => await weaponSync.GetMusicFromDatabase(playerInfo));
}
*/
} }
} }
@@ -268,7 +243,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
ConnectionReset = false ConnectionReset = false
}; };
_database = new(builder.ConnectionString); _database = new Database(builder.ConnectionString);
_ = Utility.CheckDatabaseTables(); _ = Utility.CheckDatabaseTables();

View File

@@ -9,7 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.215" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.218" />
<PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="MySqlConnector" Version="2.3.7" /> <PackageReference Include="MySqlConnector" Version="2.3.7" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

View File

@@ -15,12 +15,12 @@ namespace WeaponPaints
_config = config; _config = config;
} }
internal async Task GetPlayerData(PlayerInfo player) internal async Task GetPlayerData(PlayerInfo? player)
{ {
try try
{ {
await using MySqlConnection 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);
if (_config.Additional.GloveEnabled) if (_config.Additional.GloveEnabled)
@@ -39,15 +39,15 @@ namespace WeaponPaints
} }
} }
internal void GetKnifeFromDatabase(PlayerInfo player, MySqlConnection connection) private void GetKnifeFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid"; const string query = "SELECT `knife` FROM `wp_player_knife` WHERE `steamid` = @steamid";
string? playerKnife = connection.QueryFirstOrDefault<string>(query, new { steamid = player.SteamId }); var playerKnife = connection.QueryFirstOrDefault<string>(query, new { steamid = player.SteamId });
if (!string.IsNullOrEmpty(playerKnife)) if (!string.IsNullOrEmpty(playerKnife))
{ {
@@ -60,15 +60,15 @@ namespace WeaponPaints
} }
} }
internal void GetGloveFromDatabase(PlayerInfo player, MySqlConnection connection) private void GetGloveFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
string query = "SELECT `weapon_defindex` FROM `wp_player_gloves` WHERE `steamid` = @steamid"; const string query = "SELECT `weapon_defindex` FROM `wp_player_gloves` WHERE `steamid` = @steamid";
ushort? gloveData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId }); var gloveData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });
if (gloveData != null) if (gloveData != null)
{ {
@@ -81,28 +81,26 @@ namespace WeaponPaints
} }
} }
internal void GetAgentFromDatabase(PlayerInfo player, MySqlConnection connection) private void GetAgentFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId)) if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
string query = "SELECT `agent_ct`, `agent_t` FROM `wp_player_agents` WHERE `steamid` = @steamid"; const string query = "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) if (agentData == default) return;
{ var agentCT = agentData.Item1;
string agentCT = agentData.Item1; var agentT = agentData.Item2;
string agentT = agentData.Item2;
if (!string.IsNullOrEmpty(agentCT) || !string.IsNullOrEmpty(agentT)) if (!string.IsNullOrEmpty(agentCT) || !string.IsNullOrEmpty(agentT))
{ {
WeaponPaints.g_playersAgent[player.Slot] = ( WeaponPaints.g_playersAgent[player.Slot] = (
agentCT, agentCT,
agentT agentT
); );
}
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -111,7 +109,7 @@ namespace WeaponPaints
} }
} }
internal void GetWeaponPaintsFromDatabase(PlayerInfo player, MySqlConnection connection) private void GetWeaponPaintsFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
@@ -120,15 +118,9 @@ namespace WeaponPaints
var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>(); var weaponInfos = new ConcurrentDictionary<int, WeaponInfo>();
string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid"; const string query = "SELECT * FROM `wp_player_skins` WHERE `steamid` = @steamid";
var playerSkins = connection.Query<dynamic>(query, new { steamid = player.SteamId }); var playerSkins = connection.Query<dynamic>(query, new { steamid = player.SteamId });
if (playerSkins == null)
{
WeaponPaints.gPlayerWeaponsInfo[player.Slot] = weaponInfos;
return;
}
foreach (var row in playerSkins) foreach (var row in playerSkins)
{ {
int weaponDefIndex = row?.weapon_defindex ?? 0; int weaponDefIndex = row?.weapon_defindex ?? 0;
@@ -154,15 +146,15 @@ namespace WeaponPaints
} }
} }
internal void GetMusicFromDatabase(PlayerInfo player, MySqlConnection connection) private void GetMusicFromDatabase(PlayerInfo? player, MySqlConnection connection)
{ {
try try
{ {
if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId)) if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player?.SteamId))
return; return;
string query = "SELECT `music_id` FROM `wp_player_music` WHERE `steamid` = @steamid"; const string query = "SELECT `music_id` FROM `wp_player_music` WHERE `steamid` = @steamid";
ushort? musicData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId }); var musicData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });
if (musicData != null) if (musicData != null)
{ {
@@ -179,12 +171,13 @@ namespace WeaponPaints
internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife) internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife)
{ {
if (!_config.Additional.KnifeEnabled || player == null || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return; if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return;
const string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
string query = "INSERT INTO `wp_player_knife` (`steamid`, `knife`) VALUES(@steamid, @newKnife) ON DUPLICATE KEY UPDATE `knife` = @newKnife";
await connection.ExecuteAsync(query, new { steamid = player.SteamId, newKnife = knife }); await connection.ExecuteAsync(query, new { steamid = player.SteamId, newKnife = knife });
} }
catch (Exception e) catch (Exception e)
@@ -195,12 +188,12 @@ namespace WeaponPaints
internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex) internal async Task SyncGloveToDatabase(PlayerInfo player, int defindex)
{ {
if (!_config.Additional.GloveEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.GloveEnabled || string.IsNullOrEmpty(player.SteamId)) return;
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
string query = "INSERT INTO `wp_player_gloves` (`steamid`, `weapon_defindex`) VALUES(@steamid, @weapon_defindex) ON DUPLICATE KEY UPDATE `weapon_defindex` = @weapon_defindex"; const string query = "INSERT INTO `wp_player_gloves` (`steamid`, `weapon_defindex`) VALUES(@steamid, @weapon_defindex) ON DUPLICATE KEY UPDATE `weapon_defindex` = @weapon_defindex";
await connection.ExecuteAsync(query, new { steamid = player.SteamId, weapon_defindex = defindex }); await connection.ExecuteAsync(query, new { steamid = player.SteamId, weapon_defindex = defindex });
} }
catch (Exception e) catch (Exception e)
@@ -211,17 +204,18 @@ namespace WeaponPaints
internal async Task SyncAgentToDatabase(PlayerInfo player) internal async Task SyncAgentToDatabase(PlayerInfo player)
{ {
if (!_config.Additional.AgentEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.AgentEnabled || string.IsNullOrEmpty(player.SteamId)) return;
const string query = """
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
""";
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
string query = @"
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";
await connection.ExecuteAsync(query, new { steamid = player.SteamId, agent_ct = WeaponPaints.g_playersAgent[player.Slot].CT, agent_t = WeaponPaints.g_playersAgent[player.Slot].T }); await connection.ExecuteAsync(query, new { steamid = player.SteamId, agent_ct = WeaponPaints.g_playersAgent[player.Slot].CT, agent_t = WeaponPaints.g_playersAgent[player.Slot].T });
} }
@@ -233,25 +227,22 @@ namespace WeaponPaints
internal async Task SyncWeaponPaintsToDatabase(PlayerInfo player) internal async Task SyncWeaponPaintsToDatabase(PlayerInfo player)
{ {
if (player == null || string.IsNullOrEmpty(player.SteamId) || !WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo)) if (string.IsNullOrEmpty(player.SteamId) || !WeaponPaints.gPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponsInfo))
return; return;
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
foreach (var weaponInfoPair in weaponsInfo) foreach (var (weaponDefIndex, weaponInfo) in weaponsInfo)
{ {
int weaponDefIndex = weaponInfoPair.Key; var paintId = weaponInfo.Paint;
WeaponInfo weaponInfo = weaponInfoPair.Value; var wear = weaponInfo.Wear;
var seed = weaponInfo.Seed;
int paintId = weaponInfo.Paint; const string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
float wear = weaponInfo.Wear;
int seed = weaponInfo.Seed;
string queryCheckExistence = "SELECT COUNT(*) FROM `wp_player_skins` WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex"; var existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence, new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex });
int existingRecordCount = await connection.ExecuteScalarAsync<int>(queryCheckExistence, new { steamid = player.SteamId, weaponDefIndex });
string query; string query;
object parameters; object parameters;
@@ -259,13 +250,13 @@ namespace WeaponPaints
if (existingRecordCount > 0) if (existingRecordCount > 0)
{ {
query = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex"; query = "UPDATE `wp_player_skins` SET `weapon_paint_id` = @paintId, `weapon_wear` = @wear, `weapon_seed` = @seed WHERE `steamid` = @steamid AND `weapon_defindex` = @weaponDefIndex";
parameters = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed }; parameters = new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex, paintId, wear, seed };
} }
else else
{ {
query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " + query = "INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_paint_id`, `weapon_wear`, `weapon_seed`) " +
"VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)"; "VALUES (@steamid, @weaponDefIndex, @paintId, @wear, @seed)";
parameters = new { steamid = player.SteamId, weaponDefIndex, paintId, wear, seed }; parameters = new { steamid = player.SteamId, weaponDefIndex = weaponDefIndex, paintId, wear, seed };
} }
await connection.ExecuteAsync(query, parameters); await connection.ExecuteAsync(query, parameters);
@@ -279,12 +270,12 @@ namespace WeaponPaints
internal async Task SyncMusicToDatabase(PlayerInfo player, ushort music) internal async Task SyncMusicToDatabase(PlayerInfo player, ushort music)
{ {
if (!_config.Additional.MusicEnabled || player == null || string.IsNullOrEmpty(player.SteamId)) return; if (!_config.Additional.MusicEnabled || string.IsNullOrEmpty(player.SteamId)) return;
try try
{ {
await using var connection = await _database.GetConnectionAsync(); await using var connection = await _database.GetConnectionAsync();
string query = "INSERT INTO `wp_player_music` (`steamid`, `music_id`) VALUES(@steamid, @newMusic) ON DUPLICATE KEY UPDATE `music_id` = @newMusic"; const string query = "INSERT INTO `wp_player_music` (`steamid`, `music_id`) VALUES(@steamid, @newMusic) ON DUPLICATE KEY UPDATE `music_id` = @newMusic";
await connection.ExecuteAsync(query, new { steamid = player.SteamId, newMusic = music }); await connection.ExecuteAsync(query, new { steamid = player.SteamId, newMusic = music });
} }
catch (Exception e) catch (Exception e)