From 02208095f032162bcd612282de55fd2be719a5b8 Mon Sep 17 00:00:00 2001 From: Dawid Bepierszcz <41084667+daffyyyy@users.noreply.github.com> Date: Tue, 20 Feb 2024 01:28:25 +0100 Subject: [PATCH] test --- .github/workflows/build.yml | 2 + Commands.cs | 25 +++++++++---- Events.cs | 73 +++++++++++++++++-------------------- Utility.cs | 2 +- WeaponAction.cs | 59 +++++++++++++++++++++++------- WeaponPaints.cs | 9 ++++- WeaponSynchronization.cs | 11 +++++- gamedata/gloves.json | 16 ++++++++ 8 files changed, 134 insertions(+), 63 deletions(-) create mode 100644 gamedata/gloves.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9296f420..002bfcd5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,6 +62,8 @@ jobs: run: cp website/data/skins.json ${{ env.OUTPUT_PATH }}/skins.json - name: Copy gloves.json run: cp website/data/gloves.json ${{ env.OUTPUT_PATH }}/gloves.json + - name: Copy gamedata + run: cp -R gamedata gamedata - name: Zip uses: thedoctor0/zip-release@0.7.5 with: diff --git a/Commands.cs b/Commands.cs index 9d47b24a..4d28c92e 100644 --- a/Commands.cs +++ b/Commands.cs @@ -1,4 +1,5 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Menu; @@ -96,7 +97,7 @@ namespace WeaponPaints }); AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) => { - if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; + if (!Utility.IsPlayerValid(player)) return; OnCommandRefresh(player, info); }); if (Config.Additional.CommandKillEnabled) @@ -149,9 +150,10 @@ namespace WeaponPaints g_playersKnife[(int)player!.Index] = knifeKey; if (g_bCommandsAllowed && (LifeState_t)player.LifeState == LifeState_t.LIFE_ALIVE) - AddTimer(0.15f, () => RefreshWeapons(player), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(0.1f, () => RefreshWeapons(player), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - _ = weaponSync?.SyncKnifeToDatabase(playerInfo, knifeKey) ?? Task.CompletedTask; + if (weaponSync != null) + Task.Run(async () => await weaponSync.SyncKnifeToDatabase(playerInfo, knifeKey)); } }; foreach (var knifePair in knivesOnly) @@ -183,6 +185,7 @@ namespace WeaponPaints { var classNamesByWeapon = weaponList.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); var weaponSelectionMenu = new ChatMenu(Localizer["wp_skin_menu_weapon_title"]); + weaponSelectionMenu.PostSelectAction = PostSelectAction.Close; // Function to handle skin selection for a specific weapon var handleWeaponSelection = (CCSPlayerController? player, ChatMenuOption option) => @@ -326,6 +329,7 @@ namespace WeaponPaints private void SetupGlovesMenu() { var glovesSelectionMenu = new ChatMenu(Localizer["wp_glove_menu_title"]); + glovesSelectionMenu.PostSelectAction = PostSelectAction.Close; var handleGloveSelection = (CCSPlayerController? player, ChatMenuOption option) => { @@ -371,7 +375,15 @@ namespace WeaponPaints player!.Print(Localizer["wp_glove_menu_select", selectedPaintName]); } - _ = weaponSync?.SyncGloveToDatabase(playerInfo, (ushort)weaponDefindex, paint) ?? Task.CompletedTask; + Server.NextFrame(() => + { + RefreshGloves(player); + }); + + if (weaponSync != null) + { + Task.Run(async () => await weaponSync.SyncGloveToDatabase(playerInfo, (ushort)weaponDefindex, paint)); + } } }; }; @@ -388,7 +400,7 @@ namespace WeaponPaints // Command to open the weapon selection menu for players AddCommand($"css_{Config.Additional.CommandGlove}", "Gloves selection menu", (player, info) => { - if (!Utility.IsPlayerValid(player)) return; + if (!Utility.IsPlayerValid(player) || !g_bCommandsAllowed) return; if (player == null || player.UserId == null) return; @@ -396,7 +408,6 @@ namespace WeaponPaints DateTime.UtcNow >= (commandsCooldown.TryGetValue((int)player.UserId, out cooldownEndTime) ? cooldownEndTime : DateTime.UtcNow)) { commandsCooldown[(int)player.UserId] = DateTime.UtcNow.AddSeconds(Config.CmdRefreshCooldownSeconds); - glovesSelectionMenu.PostSelectAction = PostSelectAction.Close; MenuManager.OpenChatMenu(player, glovesSelectionMenu); return; } diff --git a/Events.cs b/Events.cs index 56faae7b..cccad032 100644 --- a/Events.cs +++ b/Events.cs @@ -1,16 +1,19 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; namespace WeaponPaints { public partial class WeaponPaints { - private void OnClientPutInServer(int playerSlot) + + [GameEventHandler] + public HookResult OnPlayerConnect(EventPlayerConnectFull @event, GameEventInfo info) { - CCSPlayerController? player = Utilities.GetPlayerFromSlot(playerSlot); + CCSPlayerController? player = @event.Userid; if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17 || - weaponSync == null) return; + weaponSync == null || _database == null) return HookResult.Continue; PlayerInfo playerInfo = new PlayerInfo { @@ -23,34 +26,37 @@ namespace WeaponPaints Task.Run(async () => { - if (Config.Additional.SkinEnabled) - await weaponSync.GetWeaponPaintsFromDatabase(playerInfo); + // Run skin, knife, and glove tasks asynchronously + var skinTask = Config.Additional.SkinEnabled ? weaponSync.GetWeaponPaintsFromDatabase(playerInfo) : Task.CompletedTask; + var knifeTask = Config.Additional.KnifeEnabled ? weaponSync.GetKnifeFromDatabase(playerInfo) : Task.CompletedTask; + var gloveTask = Config.Additional.GloveEnabled ? weaponSync.GetGloveFromDatabase(playerInfo) : Task.CompletedTask; - if (Config.Additional.KnifeEnabled) - await weaponSync.GetKnifeFromDatabase(playerInfo); - if (Config.Additional.GloveEnabled) - await weaponSync.GetGloveFromDatabase(playerInfo); + // Await all tasks to complete + await Task.WhenAll(skinTask, knifeTask, gloveTask); }); + + return HookResult.Continue; } - private void OnClientDisconnect(int playerSlot) + [GameEventHandler] + public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo info) { - CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot); + CCSPlayerController player = @event.Userid; - if (player is null || !player.IsValid || !player.UserId.HasValue || player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17) return; + if (player is null || !player.IsValid || !player.UserId.HasValue || player.IsBot || + player.IsHLTV || player.SteamID.ToString().Length != 17) return HookResult.Continue; + + if (Config.Additional.SkinEnabled) + gPlayerWeaponsInfo.TryRemove((int)player.Index, out _); if (Config.Additional.KnifeEnabled) g_playersKnife.TryRemove((int)player.Index, out _); if (Config.Additional.GloveEnabled) g_playersGlove.TryRemove(player.Index, out _); - if (Config.Additional.SkinEnabled && gPlayerWeaponsInfo.TryGetValue((int)player.Index, out var innerDictionary)) - { - innerDictionary.Clear(); - gPlayerWeaponsInfo.TryRemove((int)player.Index, out _); - } - commandsCooldown.Remove((int)player.UserId); + + return HookResult.Continue; } private void OnEntityCreated(CEntityInstance entity) @@ -153,30 +159,19 @@ namespace WeaponPaints { CCSPlayerController? player = @event.Userid; - if (player is null || !player.IsValid || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled) + if (player is null || !player.IsValid || player.PlayerPawn == null || + !player.PlayerPawn.IsValid || player.IsHLTV + || !Config.Additional.KnifeEnabled && !Config.Additional.GloveEnabled) return HookResult.Continue; - if (g_playersGlove.TryGetValue(player.Index, out var gloveInfo) && gloveInfo.Paint != 0) - { - player.PlayerPawn!.Value!.EconGloves.ItemDefinitionIndex = gloveInfo.Definition; - player.PlayerPawn!.Value!.EconGloves.ItemIDLow = 16384 & 0xFFFFFFFF; - player.PlayerPawn!.Value!.EconGloves.ItemIDHigh = 16384 >> 32; - player.PlayerPawn!.Value!.EconGloves.EntityQuality = 3; - player.PlayerPawn!.Value!.EconGloves.EntityLevel = 1; - - Server.NextFrame(() => - { - player.PlayerPawn!.Value!.EconGloves.Initialized = true; - SetPlayerBody(player, "default_gloves", 1); - SetOrAddAttributeValueByName(player.PlayerPawn!.Value!.EconGloves.NetworkedDynamicAttributes, "set item texture prefab", gloveInfo.Paint); - - Utilities.SetStateChanged(player.PlayerPawn.Value, "CCSPlayerPawn", "m_EconGloves"); - }); - } - g_knifePickupCount[(int)player.Index] = 0; GiveKnifeToPlayer(player); + Server.NextFrame(() => + { + RefreshGloves(player); + }); + return HookResult.Continue; } @@ -262,8 +257,8 @@ namespace WeaponPaints private void RegisterListeners() { RegisterListener(OnEntityCreated); - RegisterListener(OnClientPutInServer); - RegisterListener(OnClientDisconnect); + //RegisterListener(OnClientPutInServer); + //RegisterListener(OnClientDisconnect); RegisterListener(OnMapStart); RegisterListener(OnTick); diff --git a/Utility.cs b/Utility.cs index eb6359bc..fcf0927c 100644 --- a/Utility.cs +++ b/Utility.cs @@ -87,7 +87,7 @@ namespace WeaponPaints if (player is null) return false; return (player is not null && player.IsValid && !player.IsBot && !player.IsHLTV - && WeaponPaints.weaponSync != null && player.Connected == PlayerConnectedState.PlayerConnected); + && WeaponPaints.weaponSync != null && player.Connected == PlayerConnectedState.PlayerConnected && player.SteamID.ToString().Length == 17); } internal static void LoadSkinsFromFile(string filePath) diff --git a/WeaponAction.cs b/WeaponAction.cs index bab34441..885fafcf 100644 --- a/WeaponAction.cs +++ b/WeaponAction.cs @@ -1,6 +1,7 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; using Microsoft.Extensions.Logging; using System.Runtime.InteropServices; @@ -268,7 +269,7 @@ namespace WeaponPaints } player.RemoveWeapons(); - AddTimer(0.35f, () => + AddTimer(0.1f, () => { GiveKnifeToPlayer(player); @@ -348,6 +349,50 @@ namespace WeaponPaints } } + private static void RefreshGloves(CCSPlayerController player) + { + CCSPlayerPawn? pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) + return; + + string model = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance()?.ModelState.ModelName ?? string.Empty; + if (!string.IsNullOrEmpty(model)) + { + pawn.SetModel("characters/models/tm_jumpsuit/tm_jumpsuit_varianta.vmdl"); + pawn.SetModel(model); + } + + Instance.AddTimer(0.06f, () => + { + try + { + if (!player.IsValid) + return; + + if (g_playersGlove.TryGetValue(player.Index, out var gloveInfo) && gloveInfo.Paint != 0) + { + CCSPlayerPawn? pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) + return; + + CEconItemView item = pawn.EconGloves; + item.ItemDefinitionIndex = gloveInfo.Definition; + item.ItemIDLow = 16384 & 0xFFFFFFFF; + item.ItemIDHigh = 16384; + + CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture prefab", gloveInfo.Paint); + CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture seed", 0); + CAttributeList_SetOrAddAttributeValueByName.Invoke(item.NetworkedDynamicAttributes.Handle, "set item texture wear", 0.00f); + + item.Initialized = true; + + CBaseModelEntity_SetBodygroup.Invoke(pawn, "default_gloves", 1); + } + } + catch (Exception) { } + }, TimerFlags.STOP_ON_MAPCHANGE); + } + private static int GetRandomPaint(int defindex) { if (skinsList == null || skinsList.Count == 0) @@ -375,18 +420,6 @@ namespace WeaponPaints return new CSkeletonInstance(GetSkeletonInstance(node.Handle)); } - public void SetOrAddAttributeValueByName(CAttributeList attr, string name, float f) - { - var SetAttr = VirtualFunction.Create("\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x49\\x89\\xFE\\x41\\x55\\x41\\x54\\x49\\x89\\xF4\\x53\\x48\\x83\\xEC\\x78"); - SetAttr(attr.Handle, name, f); - } - - public void SetPlayerBody(CCSPlayerController player, string model, int i) - { - var SetBody = VirtualFunction.Create("\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x41\\x89\\xD5\\x41\\x54\\x49\\x89\\xFC\\x48\\x83\\xEC\\x08"); - SetBody(player.PlayerPawn.Value!.Handle, model, i); - } - private static unsafe CHandle[]? GetPlayerViewModels(CCSPlayerController player) { if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null; diff --git a/WeaponPaints.cs b/WeaponPaints.cs index 80fc2053..a559cc5f 100644 --- a/WeaponPaints.cs +++ b/WeaponPaints.cs @@ -2,6 +2,7 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using MySqlConnector; @@ -13,6 +14,7 @@ namespace WeaponPaints; [MinimumApiVersion(167)] public partial class WeaponPaints : BasePlugin, IPluginConfig { + internal static WeaponPaints Instance { get; private set; } = new(); internal static readonly Dictionary weaponList = new() { {"weapon_deagle", "Desert Eagle"}, @@ -82,7 +84,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig skinsList = new List(); internal static List glovesList = new List(); internal static WeaponSynchronization? weaponSync; - internal bool g_bCommandsAllowed = true; + public static bool g_bCommandsAllowed = true; internal Dictionary PlayerWeaponImage = new(); internal Uri GlobalShareApi = new("https://weaponpaints.fun/api.php"); @@ -90,6 +92,9 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig commandsCooldown = new Dictionary(); internal static Database? _database; + internal static MemoryFunctionVoid CAttributeList_SetOrAddAttributeValueByName = new(GameData.GetSignature("CAttributeList_SetOrAddAttributeValueByName")); + internal static MemoryFunctionVoid CBaseModelEntity_SetBodygroup = new(GameData.GetSignature("CBaseModelEntity_SetBodygroup")); + public static Dictionary WeaponDefindex { get; } = new Dictionary { { 1, "weapon_deagle" }, @@ -162,6 +167,8 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig(query, new { steamid = player.SteamId }); + // Check if glove data is retrieved successfully if (gloveData != default) { + // Update g_playersGlove dictionary with glove data WeaponPaints.g_playersGlove[(uint)player.Index] = gloveData; } } catch (Exception e) { - Utility.Log(e.Message); - return; + // Log any exceptions occurred during database operation + Utility.Log("An error occurred while fetching glove data: " + e.Message); } } diff --git a/gamedata/gloves.json b/gamedata/gloves.json new file mode 100644 index 00000000..043048b1 --- /dev/null +++ b/gamedata/gloves.json @@ -0,0 +1,16 @@ +{ + "CAttributeList_SetOrAddAttributeValueByName": { + "signatures": { + "library": "server", + "windows": "\\x40\\x53\\x41\\x56\\x41\\x57\\x48\\x81\\xEC\\x90\\x00\\x00\\x00\\x0F\\x29\\x74\\x24\\x70", + "linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x49\\x89\\xFE\\x41\\x55\\x41\\x54\\x49\\x89\\xF4\\x53\\x48\\x83\\xEC\\x78" + } + }, + "CBaseModelEntity_SetBodygroup": { + "signatures": { + "library": "server", + "windows": "\\x48\\x89\\x5C\\x24\\x08\\x48\\x89\\x74\\x24\\x10\\x57\\x48\\x83\\xEC\\x20\\x41\\x8B\\xF8\\x48\\x8B\\xF2\\x48\\x8B\\xD9\\xE8\\x2A\\x2A\\x2A\\x2A", + "linux": "\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x41\\x89\\xD5\\x41\\x54\\x49\\x89\\xFC\\x48\\x83\\xEC\\x08" + } + } +} \ No newline at end of file