diff --git a/Store/src/api/api.cs b/Store/src/api/api.cs index db688c7..d3911c0 100644 --- a/Store/src/api/api.cs +++ b/Store/src/api/api.cs @@ -7,8 +7,29 @@ namespace Store; public class StoreAPI : IStoreApi { - public StoreAPI() + public event Action>? OnPlayerPurchaseItem; + public event Action>? OnPlayerEquipItem; + public event Action>? OnPlayerUnequipItem; + public event Action>? OnPlayerSellItem; + + public void PlayerPurchaseItem(CCSPlayerController player, Dictionary item) + { + OnPlayerPurchaseItem?.Invoke(player, item); + } + + public void PlayerEquipItem(CCSPlayerController player, Dictionary item) + { + OnPlayerEquipItem?.Invoke(player, item); + } + + public void PlayerUnequipItem(CCSPlayerController player, Dictionary item) + { + OnPlayerUnequipItem?.Invoke(player, item); + } + + public void PlayerSellItem(CCSPlayerController player, Dictionary item) { + OnPlayerSellItem?.Invoke(player, item); } public string GetDatabaseString() diff --git a/Store/src/config/config.cs b/Store/src/config/config.cs index 4dcdb03..8b3ecd5 100644 --- a/Store/src/config/config.cs +++ b/Store/src/config/config.cs @@ -17,12 +17,31 @@ public static class Config_Config { public static Cfg Config { get; set; } = new Cfg(); + private static readonly string ConfigPath; + + static Config_Config() + { + string assemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? string.Empty; + + ConfigPath = Path.Combine(Server.GameDirectory, + "csgo", + "addons", + "counterstrikesharp", + "configs", + "plugins", + assemblyName, + "config.toml" + ); + } + public static void Load() { - string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? ""; - string CfgPath = $"{Server.GameDirectory}/csgo/addons/counterstrikesharp/configs/plugins/{AssemblyName}"; + if (!File.Exists(ConfigPath)) + { + throw new FileNotFoundException($"Configuration file not found: {ConfigPath}"); + } - LoadConfig($"{CfgPath}/config.toml"); + LoadConfig(ConfigPath); Task.Run(async () => { diff --git a/Store/src/cs2-store.cs b/Store/src/cs2-store.cs index e05f02c..ef16ad5 100644 --- a/Store/src/cs2-store.cs +++ b/Store/src/cs2-store.cs @@ -9,7 +9,7 @@ namespace Store; public class Store : BasePlugin, IPluginConfig { public override string ModuleName => "Store"; - public override string ModuleVersion => "1.6"; + public override string ModuleVersion => "1.7"; public override string ModuleAuthor => "schwarper"; public Item_Config Config { get; set; } = new Item_Config(); @@ -22,10 +22,11 @@ public class Store : BasePlugin, IPluginConfig public static Store Instance { get; set; } = new(); public Random Random { get; set; } = new(); public Dictionary GlobalGiftTimeout { get; set; } = []; + public static StoreAPI Api { get; set; } = new(); public override void Load(bool hotReload) { - Capabilities.RegisterPluginCapability(IStoreApi.Capability, () => new StoreAPI()); + Capabilities.RegisterPluginCapability(IStoreApi.Capability, () => Api); Instance = this; diff --git a/Store/src/event/event.cs b/Store/src/event/event.cs index e7d9e72..074944b 100644 --- a/Store/src/event/event.cs +++ b/Store/src/event/event.cs @@ -35,7 +35,7 @@ public static void Load() Instance.RegisterEventHandler(OnPlayerDeath); Instance.RegisterListener(OnClientAuthorized); - Instance.AddTimer(5.0F, () => + Instance.AddTimer(5.0f, () => { StartCreditsTimer(); }); @@ -50,16 +50,11 @@ public static void StartCreditsTimer() return; } - foreach (CCSPlayerController player in Utilities.GetPlayers()) + List players = Utilities.GetPlayers(); + + foreach (CCSPlayerController player in players) { - if (player == null - || !player.IsValid - || player.PlayerPawn == null - || !player.PlayerPawn.IsValid - || player.PlayerPawn.Value == null - || player.UserId == null - || player.IsBot - || player.IsHLTV) + if (player.IsBot) { continue; } @@ -96,11 +91,6 @@ public static void OnMapStart(string mapname) type.MapStart(); }); - Instance.AddTimer(5.0F, () => - { - GameRules.GlobalGameRules = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").First().GameRules!; - }, TimerFlags.STOP_ON_MAPCHANGE); - Database.ExecuteAsync("DELETE FROM store_items WHERE DateOfExpiration < NOW() AND DateOfExpiration > '0001-01-01 00:00:00';", null); List itemsToRemove = Instance.GlobalStorePlayerItems diff --git a/Store/src/gamerules/gamerules.cs b/Store/src/gamerules/gamerules.cs index 99002ba..87568d8 100644 --- a/Store/src/gamerules/gamerules.cs +++ b/Store/src/gamerules/gamerules.cs @@ -7,20 +7,32 @@ namespace Store; public static class GameRules { - public static CCSGameRules GlobalGameRules { get; set; } = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").First().GameRules!; + private static CCSGameRulesProxy? GameRulesProxy; + private static readonly ConVar mp_halftime = ConVar.Find("mp_halftime")!; + private static readonly ConVar mp_maxrounds = ConVar.Find("mp_maxrounds")!; public static bool IgnoreWarmUp() { - return Config.Credits.IgnoreWarmup && GlobalGameRules.WarmupPeriod; + if (GameRulesProxy?.IsValid is not true) + { + GameRulesProxy = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").FirstOrDefault(); + } + + return Config.Credits.IgnoreWarmup && (GameRulesProxy?.GameRules?.WarmupPeriod ?? false); } public static bool IsPistolRound() { - bool halftime = ConVar.Find("mp_halftime")!.GetPrimitiveValue(); - int maxrounds = ConVar.Find("mp_maxrounds")!.GetPrimitiveValue(); + if (GameRulesProxy?.IsValid is not true) + { + GameRulesProxy = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").FirstOrDefault(); + } + + bool halftime = mp_halftime.GetPrimitiveValue(); + int maxrounds = mp_maxrounds.GetPrimitiveValue(); - return GlobalGameRules.TotalRoundsPlayed == 0 || - (halftime && maxrounds / 2 == GlobalGameRules.TotalRoundsPlayed) || - GlobalGameRules.GameRestart; + return GameRulesProxy?.GameRules?.TotalRoundsPlayed == 0 || + (halftime && maxrounds / 2 == GameRulesProxy?.GameRules?.TotalRoundsPlayed) || + (GameRulesProxy?.GameRules?.GameRestart ?? false); } } diff --git a/Store/src/item/item.cs b/Store/src/item/item.cs index 5e09e32..b4ceeff 100644 --- a/Store/src/item/item.cs +++ b/Store/src/item/item.cs @@ -10,6 +10,8 @@ namespace Store; public static class Item { + public static bool IsHidden(this Dictionary item) => item.ContainsKey("hide") && item["hide"] == "true"; + public static bool Give(CCSPlayerController player, Dictionary item) { Store_Item_Types? type = Instance.GlobalStoreItemTypes.FirstOrDefault(i => i.Type == item["type"]); @@ -43,6 +45,8 @@ public static bool Give(CCSPlayerController player, Dictionary i Instance.GlobalStorePlayerItems.Add(playeritem); + Store.Api.PlayerEquipItem(player, item); + Server.NextFrame(() => { Database.SavePlayerItem(player, playeritem); @@ -87,7 +91,7 @@ public static bool Purchase(CCSPlayerController player, Dictionary 0) { @@ -96,6 +100,8 @@ public static bool Purchase(CCSPlayerController player, Dictionary { Database.SavePlayerItem(player, playeritem); @@ -176,6 +184,8 @@ public static bool Equip(CCSPlayerController player, Dictionary Instance.GlobalStorePlayerEquipments.Add(playeritem); + Store.Api.PlayerEquipItem(player, item); + Server.NextFrame(() => { Database.SavePlayerEquipment(player, playeritem); @@ -200,6 +210,8 @@ public static bool Unequip(CCSPlayerController player, Dictionary p.SteamID == player.SteamID && p.UniqueId == item["uniqueid"]); + Store.Api.PlayerUnequipItem(player, item); + Server.NextFrame(() => { Database.RemovePlayerEquipment(player, item["uniqueid"]); @@ -223,6 +235,8 @@ public static bool Sell(CCSPlayerController player, Dictionary i Instance.GlobalStorePlayerItems.Remove(playeritem); + Store.Api.PlayerSellItem(player, item); + Server.NextFrame(() => { Database.RemovePlayerItem(player, playeritem); diff --git a/Store/src/item/items/playerskin.cs b/Store/src/item/items/playerskin.cs index eada5ee..0fc6466 100644 --- a/Store/src/item/items/playerskin.cs +++ b/Store/src/item/items/playerskin.cs @@ -56,7 +56,7 @@ public static bool OnEquip(CCSPlayerController player, Dictionary p.Value.TryGetValue("slot", out string? slot) && slot == Slot.ToString())) || - (inventory && !playerSkinItems.Any(item => Item.PlayerHas(player, item.Value["type"], item.Value["uniqueid"], false)))) + if (!IsAnyItemExistInPlayerSkins(player, Slot, inventory, playerSkinItems)) { continue; } @@ -166,8 +172,6 @@ public static void DisplayItem(CCSPlayerController player, bool inventory, strin continue; } - bool isHidden = item.ContainsKey("hide") && item["hide"] == "true"; - if (Item.PlayerHas(player, item["type"], item["uniqueid"], false)) { AddMenuOption(player, menu, (player, option) => @@ -176,7 +180,7 @@ public static void DisplayItem(CCSPlayerController player, bool inventory, strin DisplayItemOption(player, item, option); }, item["name"]); } - else if (!inventory && !isHidden) + else if (!inventory && !item.IsHidden()) { if (int.Parse(item["price"]) <= 0) { @@ -354,7 +358,7 @@ public static void OnTick() public static bool CheckFlag(CCSPlayerController player, Dictionary item) { - if (!item.TryGetValue("flag", out var flag) || string.IsNullOrWhiteSpace(flag)) + if (!item.TryGetValue("flag", out string? flag) || string.IsNullOrWhiteSpace(flag)) { return true; } @@ -385,4 +389,14 @@ public static bool CheckPermissionOrSteamID(CCSPlayerController player, string k return key == player.SteamID.ToString(); } + + public static bool IsAnyItemExistInPlayerSkins(CCSPlayerController player, int Slot, bool inventory, Dictionary> playerSkinItems) + { + return + playerSkinItems.Select(i => i.Value).Any(item => + CheckFlag(player, item) && + (item.IsHidden() && Item.PlayerHas(player, item["type"], item["uniqueid"], false) || !item.IsHidden()) && + item.TryGetValue("slot", out string? slot) && slot == Slot.ToString()) || + (inventory && playerSkinItems.Any(item => Item.PlayerHas(player, item.Value["type"], item.Value["uniqueid"], false))); + } } \ No newline at end of file diff --git a/Store/src/menu/oldmenu.cs b/Store/src/menu/oldmenu.cs index a3b00b4..a2a96e1 100644 --- a/Store/src/menu/oldmenu.cs +++ b/Store/src/menu/oldmenu.cs @@ -61,8 +61,7 @@ public static void DisplayItems(CCSPlayerController player, string key, Dictiona foreach (int Slot in new[] { 1, 2, 3 }) { - if ((!playerSkinItems.Any(p => p.Value.TryGetValue("slot", out string? slot) && slot == Slot.ToString())) || - (inventory && !playerSkinItems.Any(item => Item.PlayerHas(player, item.Value["type"], item.Value["uniqueid"], false)))) + if (!Menu.IsAnyItemExistInPlayerSkins(player, Slot, inventory, playerSkinItems)) { continue; } @@ -106,8 +105,6 @@ public static void DisplayItem(CCSPlayerController player, bool inventory, strin continue; } - bool isHidden = item.ContainsKey("hide") && item["hide"] == "true"; - if (Item.PlayerHas(player, item["type"], item["uniqueid"], false)) { AddMenuOption(player, menu, (player, option) => @@ -116,7 +113,7 @@ public static void DisplayItem(CCSPlayerController player, bool inventory, strin DisplayItemOption(player, item); }, false, item["name"]); } - else if (!inventory && !isHidden) + else if (!inventory && !item.IsHidden()) { if (int.Parse(item["price"]) <= 0) { @@ -124,7 +121,7 @@ public static void DisplayItem(CCSPlayerController player, bool inventory, strin } else { - AddMenuOption(player, menu, (player, option) => SelectPurchase(player, item, true), true, "menu_store", item["name"], item["price"]); + AddMenuOption(player, menu, (player, option) => SelectPurchase(player, item, true), false, "menu_store", item["name"], item["price"]); } } } diff --git a/StoreApi/IStoreApi.cs b/StoreApi/IStoreApi.cs index eaee8d9..b058364 100644 --- a/StoreApi/IStoreApi.cs +++ b/StoreApi/IStoreApi.cs @@ -9,6 +9,11 @@ public interface IStoreApi { public static readonly PluginCapability Capability = new("store:api"); + public event Action>? OnPlayerPurchaseItem; + public event Action>? OnPlayerEquipItem; + public event Action>? OnPlayerUnequipItem; + public event Action>? OnPlayerSellItem; + public string GetDatabaseString(); public int GetPlayerCredits(CCSPlayerController player); public int SetPlayerCredits(CCSPlayerController player, int credits);