Skip to content

Commit

Permalink
Merge pull request #312 from originalaidn/main
Browse files Browse the repository at this point in the history
added pins and stattrak - not ingame for now
  • Loading branch information
daffyyyy authored Oct 18, 2024
2 parents d9adaa4 + 2bc53cd commit 1ff3fe9
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 25 deletions.
3 changes: 3 additions & 0 deletions Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ private void OnCommandRefresh(CCSPlayerController? player, CommandInfo command)

GivePlayerGloves(player);
RefreshWeapons(player);
GivePlayerAgent(player);
GivePlayerMusicKit(player);
AddTimer(0.15f, () => GivePlayerPin(player));
}

if (!string.IsNullOrEmpty(Localizer["wp_command_refresh_done"]))
Expand Down
7 changes: 5 additions & 2 deletions Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class Additional
[JsonPropertyName("SkinEnabled")]
public bool SkinEnabled { get; set; } = true;

[JsonPropertyName("PinsEnabled")]
public bool PinsEnabled { get; set; } = true;

[JsonPropertyName("CommandWpEnabled")]
public bool CommandWpEnabled { get; set; } = true;

Expand Down Expand Up @@ -62,7 +65,7 @@ public class Additional

public class WeaponPaintsConfig : BasePluginConfig
{
[JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 7;
[JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 8;

[JsonPropertyName("SkinsLanguage")]
public string SkinsLanguage { get; set; } = "en";
Expand All @@ -88,7 +91,7 @@ public class WeaponPaintsConfig : BasePluginConfig
[JsonPropertyName("Website")]
public string Website { get; set; } = "example.com/skins";

[JsonPropertyName("Additionalss")]
[JsonPropertyName("Additional")]
public Additional Additional { get; set; } = new();
}
}
54 changes: 52 additions & 2 deletions Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using System.Runtime.InteropServices;

namespace WeaponPaints
{
Expand Down Expand Up @@ -68,6 +67,22 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo

if (player is null || !player.IsValid || player.IsBot) return HookResult.Continue;

var 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 (!GPlayerWeaponsInfo.TryGetValue(player.Slot, out var weaponInfos))
return HookResult.Continue;

if (WeaponSync != null)
_ = Task.Run(async () => await WeaponSync.SyncStatTrakToDatabase(playerInfo, weaponInfos));

if (Config.Additional.SkinEnabled)
{
GPlayerWeaponsInfo.TryRemove(player.Slot, out _);
Expand All @@ -88,9 +103,12 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo
{
GPlayersMusic.TryRemove(player.Slot, out _);
}
if (Config.Additional.PinsEnabled)
{
GPlayersPin.TryRemove(player.Slot, out _);
}

_temporaryPlayerWeaponWear.TryRemove(player.Slot, out _);

CommandsCooldown.Remove(player.Slot);

return HookResult.Continue;
Expand Down Expand Up @@ -231,6 +249,37 @@ public HookResult OnItemPickup(EventItemPickup @event, GameEventInfo _)
return HookResult.Continue;
}

private HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info)
{
CCSPlayerController? player = @event.Attacker;

if (player is null || !player.IsValid)
return HookResult.Continue;

if (!GPlayerWeaponsInfo.TryGetValue(player.Slot, out _)) return HookResult.Continue;

CBasePlayerWeapon? weapon = player.PlayerPawn.Value?.WeaponServices?.ActiveWeapon.Value;

if (weapon == null) return HookResult.Continue;

int weaponDefIndex = weapon.AttributeManager.Item.ItemDefinitionIndex;

if (!GPlayerWeaponsInfo[player.Slot].TryGetValue(weaponDefIndex, out var weaponInfo) || weaponInfo.Paint == 0)
return HookResult.Continue;

if (!weaponInfo.StatTrak) return HookResult.Continue;

weaponInfo.StatTrakCount += 1;

CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater", ViewAsFloat((uint)weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater score type", 0);

CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater", ViewAsFloat((uint)weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater score type", 0);

return HookResult.Continue;
}

private void RegisterListeners()
{
RegisterListener<Listeners.OnMapStart>(OnMapStart);
Expand All @@ -239,6 +288,7 @@ private void RegisterListeners()
RegisterEventHandler<EventRoundStart>(OnRoundStart);
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
RegisterListener<Listeners.OnEntityCreated>(OnEntityCreated);
RegisterEventHandler<EventPlayerDeath>(OnPlayerDeath);

if (Config.Additional.ShowSkinImage)
RegisterListener<Listeners.OnTick>(OnTick);
Expand Down
9 changes: 9 additions & 0 deletions Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ internal static async Task CheckDatabaseTables()
`weapon_wear` float NOT NULL DEFAULT 0.000001,
`weapon_seed` int(16) NOT NULL DEFAULT 0,
`weapon_nametag` VARCHAR(128) DEFAULT NULL,
`weapon_stattrak` tinyint(1) NOT NULL,
`weapon_stattrak_count` int(10) NOT NULL,
`weapon_sticker_0` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_1` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
`weapon_sticker_2` VARCHAR(128) NOT NULL DEFAULT '0;0;0;0;0;0;0' COMMENT 'id;schema;x;y;wear;scale;rotation',
Expand Down Expand Up @@ -68,6 +70,13 @@ internal static async Task CheckDatabaseTables()
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
"""
CREATE TABLE IF NOT EXISTS `wp_player_pins` (
`steamid` varchar(64) NOT NULL,
`id` int(11) NOT NULL,
UNIQUE (`steamid`)
) ENGINE=InnoDB
""",
];

foreach (var query in createTableQueries)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.6a
2.7a
1 change: 1 addition & 0 deletions Variables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public partial class WeaponPaints
internal static readonly ConcurrentDictionary<int, string> GPlayersKnife = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersGlove = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersMusic = new();
internal static readonly ConcurrentDictionary<int, ushort> GPlayersPin = new();
public static readonly ConcurrentDictionary<int, (string? CT, string? T)> GPlayersAgent = new();
internal static readonly ConcurrentDictionary<int, ConcurrentDictionary<int, WeaponInfo>> GPlayerWeaponsInfo = new();
internal static List<JObject> SkinsList = [];
Expand Down
39 changes: 23 additions & 16 deletions WeaponAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using CounterStrikeSharp.API.Modules.Utils;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Runtime.InteropServices;

namespace WeaponPaints
Expand Down Expand Up @@ -87,6 +86,15 @@ private void GivePlayerWeaponSkin(CCSPlayerController player, CBasePlayerWeapon
weapon.FallbackWear = weaponInfo.Wear;
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);

if (weaponInfo.StatTrak)
{
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater", ViewAsFloat((uint)weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "kill eater score type", 0);

CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater", ViewAsFloat((uint)weaponInfo.StatTrakCount));
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "kill eater score type", 0);
}

fallbackPaintKit = weapon.FallbackPaintKit;

if (fallbackPaintKit == 0)
Expand Down Expand Up @@ -451,6 +459,19 @@ private static void GivePlayerMusicKit(CCSPlayerController player)
player.MusicKitID = value;
Utilities.SetStateChanged(player, "CCSPlayerController", "m_iMusicKitID");
}

private static void GivePlayerPin(CCSPlayerController player)
{
if (!GPlayersPin.TryGetValue(player.Slot, out var pin)) return;

if (player.InventoryServices == null) return;

for (var index = 0; index < player.InventoryServices.Rank.Length; index++)
{
player.InventoryServices.Rank[index] = index == 5 ? (MedalRank_t)pin : MedalRank_t.MEDAL_RANK_NONE;
Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInventoryServices");
}
}

private void GiveOnItemPickup(CCSPlayerController player)
{
Expand Down Expand Up @@ -496,21 +517,7 @@ private void UpdatePlayerEconItemId(CEconItemView econItemView)
return viewModel.Value == null ? null : viewModel.Value;
}

public static unsafe T[] GetFixedArray<T>(nint pointer, string @class, string member, int length) where T : CHandle<CBaseViewModel>
{
var ptr = pointer + Schema.GetSchemaOffset(@class, member);
var references = MemoryMarshal.CreateSpan(ref ptr, length);
var values = new T[length];

for (var i = 0; i < length; i++)
{
values[i] = (T)Activator.CreateInstance(typeof(T), references[i])!;
}

return values;
}

private float ViewAsFloat(uint value)
private static float ViewAsFloat(uint value)
{
return BitConverter.Int32BitsToSingle((int)value);
}
Expand Down
8 changes: 5 additions & 3 deletions WeaponInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
public class WeaponInfo
{
public int Paint { get; set; }
public int Seed { get; set; } = 0;
public float Wear { get; set; } = 0f;
public int Seed { get; set; }
public float Wear { get; set; }
public string Nametag { get; set; } = "";
public bool StatTrak { get; set; } = false;
public int StatTrakCount { get; set; }
public KeyChainInfo? KeyChain { get; set; }
public List<StickerInfo> Stickers { get; set; } = new List<StickerInfo>();
public List<StickerInfo> Stickers { get; set; } = new();
}

public class StickerInfo
Expand Down
5 changes: 4 additions & 1 deletion WeaponPaints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public partial class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig
public override string ModuleAuthor => "Nereziel & daffyy";
public override string ModuleDescription => "Skin, gloves, agents and knife selector, standalone and web-based";
public override string ModuleName => "WeaponPaints";
public override string ModuleVersion => "2.6a";
public override string ModuleVersion => "2.7a";

public override void Load(bool hotReload)
{
Expand All @@ -36,6 +36,7 @@ public override void Load(bool hotReload)
GPlayersKnife.TryRemove(player.Slot, out _);
GPlayersGlove.TryRemove(player.Slot, out _);
GPlayersAgent.TryRemove(player.Slot, out _);
GPlayersPin.TryRemove(player.Slot, out _);

var playerInfo = new PlayerInfo
{
Expand All @@ -52,6 +53,8 @@ public override void Load(bool hotReload)
if (WeaponSync != null) await WeaponSync.GetPlayerData(playerInfo);
});
}

AddTimer(2.0f, () => OnAllPluginsLoaded(hotReload));
}

Utility.LoadSkinsFromFile(ModuleDirectory + $"/data/skins_{_config.SkinsLanguage}.json", Logger);
Expand Down
66 changes: 66 additions & 0 deletions WeaponSynchronization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ internal async Task GetPlayerData(PlayerInfo? player)
GetMusicFromDatabase(player, connection);
if (_config.Additional.SkinEnabled)
GetWeaponPaintsFromDatabase(player, connection);
if (_config.Additional.PinsEnabled)
GetPinsFromDatabase(player, connection);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -235,6 +237,27 @@ private void GetMusicFromDatabase(PlayerInfo? player, MySqlConnection connection
}
}

private void GetPinsFromDatabase(PlayerInfo? player, MySqlConnection connection)
{
try
{
if (string.IsNullOrEmpty(player?.SteamId))
return;

const string query = "SELECT `id` FROM `wp_player_pins` WHERE `steamid` = @steamid";
var pinData = connection.QueryFirstOrDefault<ushort?>(query, new { steamid = player.SteamId });

if (pinData != null)
{
WeaponPaints.GPlayersPin[player.Slot] = pinData.Value;
}
}
catch (Exception ex)
{
Utility.Log($"An error occurred in GetPinsFromDatabase: {ex.Message}");
}
}

internal async Task SyncKnifeToDatabase(PlayerInfo player, string knife)
{
if (!_config.Additional.KnifeEnabled || string.IsNullOrEmpty(player.SteamId) || string.IsNullOrEmpty(knife)) return;
Expand Down Expand Up @@ -349,5 +372,48 @@ internal async Task SyncMusicToDatabase(PlayerInfo player, ushort music)
Utility.Log($"Error syncing music kit to database: {e.Message}");
}
}

internal async Task SyncStatTrakToDatabase(PlayerInfo player, ConcurrentDictionary<int,WeaponInfo> weaponInfos)
{
if (WeaponPaints.WeaponSync == null || weaponInfos.IsEmpty) return;

var statTrakWeapons = weaponInfos
.Where(w => w.Value is { StatTrak: true, StatTrakCount: > 0 })
.ToDictionary(w => w.Key, w => w.Value.StatTrakCount);

if (statTrakWeapons.Count == 0) return;

if (string.IsNullOrEmpty(player.SteamId))
return;

try
{
await using var connection = await _database.GetConnectionAsync();
await using var transaction = await connection.BeginTransactionAsync();

foreach (var (defindex, statTrakCount) in statTrakWeapons)
{
const string query = @"
INSERT INTO `wp_player_skins` (`steamid`, `weapon_defindex`, `weapon_stattrak_count`)
VALUES (@steamid, @weaponDefIndex, @StatTrakCount)
ON DUPLICATE KEY UPDATE `weapon_stattrak_count` = @StatTrakCount";

var parameters = new
{
steamid = player.SteamId,
weaponDefIndex = defindex,
StatTrakCount = statTrakCount
};

await connection.ExecuteAsync(query, parameters, transaction);
}

await transaction.CommitAsync();
}
catch (Exception e)
{
Utility.Log($"Error syncing stattrak to database: {e.Message}");
}
}
}
}

0 comments on commit 1ff3fe9

Please sign in to comment.