From b3a4ab2b6268d530b9cfe6066d965c053a1eedd9 Mon Sep 17 00:00:00 2001 From: Don Date: Tue, 21 Jul 2026 14:19:22 -0700 Subject: [PATCH] revert(shop): remove on-screen ping shop menu (A1/A2) from main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ping-opened on-screen shop menu (center-HTML render, W/S/E navigation — PRs #34, #35, #39) isn't working reliably, so pull it from main for now to unblock a prod release. Ping falls back to the previous behavior: chat-based shop list (css_shop list) with css_0..9 quick-buy aliases. Menu development continues on dev. +semver: patch --- TTT/CS2/Command/PlayerPingShopAlias.cs | 127 +++---------------------- 1 file changed, 11 insertions(+), 116 deletions(-) diff --git a/TTT/CS2/Command/PlayerPingShopAlias.cs b/TTT/CS2/Command/PlayerPingShopAlias.cs index c5e2d52..fa8cb86 100644 --- a/TTT/CS2/Command/PlayerPingShopAlias.cs +++ b/TTT/CS2/Command/PlayerPingShopAlias.cs @@ -1,10 +1,5 @@ -using System.Linq; -using System.Text; -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Timers; -using CounterStrikeSharp.API.Modules.Utils; using Microsoft.Extensions.DependencyInjection; using ShopAPI; using TTT.API; @@ -13,9 +8,6 @@ namespace TTT.CS2.Command; -// Ping opens an on-screen, navigable shop menu — no key binds required: -// W / S -> move the highlight, E (use) -> buy it, ping again -> close. -// css_0..css_9 are kept as an optional quick-buy for anyone who does bind keys. public class PlayerPingShopAlias(IServiceProvider provider) : IPluginModule { private readonly IPlayerConverter converter = provider.GetRequiredService>(); @@ -23,138 +15,41 @@ public class PlayerPingShopAlias(IServiceProvider provider) : IPluginModule { private readonly IItemSorter itemSorter = provider.GetRequiredService(); - private readonly IShop shop = provider.GetRequiredService(); - - private sealed class Menu { - public required List Items; - public int Balance; - public int Selected; - public DateTime Expiry; - } - - // slot -> open menu. Re-rendered on a timer; navigated via the buttons hook. - private readonly Dictionary open = new(); - private const int MenuSeconds = 15; - public void Dispose() { } public void Start() { } public void Start(BasePlugin? plugin) { plugin?.AddCommandListener("player_ping", onPlayerPing, HookMode.Post); - plugin?.RegisterListener< - CounterStrikeSharp.API.Core.Listeners.OnPlayerButtonsChanged>(onButtons); - - // Center HTML only shows for a moment, so re-send it while the menu is open. - plugin?.AddTimer(0.25f, refresh, TimerFlags.REPEAT); for (var i = 0; i < 10; i++) { - var index = i; // capture + var index = i; // Capture variable plugin?.AddCommand($"css_{index}", "", (player, _) => { onButton(player, index); }); } } - // Ping toggles the menu open/closed. private HookResult onPlayerPing(CCSPlayerController? player, CommandInfo commandInfo) { - if (player == null || !player.IsValid) return HookResult.Continue; - - var slot = player.Slot; - if (open.Remove(slot)) return HookResult.Continue; // re-ping closes it - - if (converter.GetPlayer(player) is not IOnlinePlayer apiPlayer) - return HookResult.Continue; - - // Snapshot + lock the sorted order, then open the menu once we have balance. - var items = itemSorter.GetSortedItems(apiPlayer, true); - Task.Run(async () => { - var balance = await shop.Load(apiPlayer); - Server.NextWorldUpdate(() => { - open[slot] = new Menu { - Items = items, Balance = balance, Selected = 0, - Expiry = DateTime.Now.AddSeconds(MenuSeconds) - }; - }); - }); - + if (player == null) return HookResult.Continue; + var gamePlayer = converter.GetPlayer(player) as IOnlinePlayer; + var cmdInfo = + new CS2CommandInfo(provider, gamePlayer, 0, "css_shop", "list"); + cmdInfo.CallingContext = CommandCallingContext.Chat; + provider.GetRequiredService().ProcessCommand(cmdInfo); return HookResult.Continue; } - // W/S move the highlight; E (use) buys the highlighted item. Only active while - // the player has the menu open, so normal movement is unaffected otherwise. - private void onButtons(CCSPlayerController player, PlayerButtons pressed, - PlayerButtons released) { - if (!player.IsValid || !open.TryGetValue(player.Slot, out var menu)) return; - if (menu.Items.Count == 0) return; - - if (pressed.HasFlag(PlayerButtons.Forward)) { - menu.Selected = (menu.Selected - 1 + menu.Items.Count) % menu.Items.Count; - menu.Expiry = DateTime.Now.AddSeconds(MenuSeconds); - } else if (pressed.HasFlag(PlayerButtons.Back)) { - menu.Selected = (menu.Selected + 1) % menu.Items.Count; - menu.Expiry = DateTime.Now.AddSeconds(MenuSeconds); - } else if (pressed.HasFlag(PlayerButtons.Use)) { - var index = menu.Selected; - open.Remove(player.Slot); - buyIndex(player, index); - } - } - - private void refresh() { - if (open.Count == 0) return; - var now = DateTime.Now; - foreach (var slot in open.Keys.ToList()) { - var menu = open[slot]; - var controller = Utilities.GetPlayerFromSlot(slot); - if (now > menu.Expiry - || controller is not { IsValid: true, PawnIsAlive: true }) { - open.Remove(slot); - continue; - } - - if (converter.GetPlayer(controller) is IOnlinePlayer apiPlayer) - controller.PrintToCenterHtml(buildHtml(apiPlayer, menu)); - } - } - - private string buildHtml(IOnlinePlayer apiPlayer, Menu menu) { - var sb = new StringBuilder(); - sb.Append( - $"=(eGO)= SHOP {menu.Balance} credits
"); - - for (var i = 0; i < menu.Items.Count; i++) { - var item = menu.Items[i]; - var selected = i == menu.Selected; - var canBuy = item.CanPurchase(apiPlayer) == PurchaseResult.SUCCESS - && item.Config.Price <= menu.Balance; - var color = selected ? "#ffd700" : canBuy ? "#7CFC00" : "#888888"; - var cursor = selected ? "▶ " : "   "; - sb.Append( - $"{cursor}{item.Name} — {item.Config.Price}
"); - } - - sb.Append( - "W / S move  •  E buy  •  ping again to close"); - return sb.ToString(); - } - private void onButton(CCSPlayerController? player, int index) { - // css_N quick-buy: css_1 -> item 1, etc. (item index-1). - if (player != null) buyIndex(player, index - 1); - } - - private void buyIndex(CCSPlayerController player, int index) { - if (index < 0) return; + if (player == null) return; if (converter.GetPlayer(player) is not IOnlinePlayer apiPlayer) return; var lastUpdated = itemSorter.GetLastUpdate(apiPlayer); if (lastUpdated == null || DateTime.Now - lastUpdated > TimeSpan.FromSeconds(20)) return; - var cmdInfo = new CS2CommandInfo(provider, apiPlayer, 0, "css_shop", "buy", - index.ToString()) { CallingContext = CommandCallingContext.Chat }; + (index - 1).ToString()) { CallingContext = CommandCallingContext.Chat }; provider.GetRequiredService().ProcessCommand(cmdInfo); itemSorter.InvalidateOrder(apiPlayer); } -} +} \ No newline at end of file