### Complete Counter-Strike 2 GSI Application Example Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt A minimal console application demonstrating GSI setup, config generation, multiple event subscriptions, and graceful shutdown. It handles various game events and provides a way to exit the application. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; class Program { static GameStateListener? _gsl; static void Main() { _gsl = new GameStateListener(4000); if (!_gsl.GenerateGSIConfigFile("MyApp")) Console.WriteLine("[WARN] Could not write GSI config."); _gsl.NewGameState += gs => { /* raw state access */ }; _gsl.BombPlanting += e => Console.WriteLine($"{e.Player.Name} planting..."); _gsl.BombPlanted += _ => Console.WriteLine("💣 Bomb planted!"); _gsl.BombDefused += _ => Console.WriteLine("✅ Bomb defused!"); _gsl.BombExploded += _ => Console.WriteLine("💥 BOOM!"); _gsl.PlayerGotKill += e => Console.WriteLine($"🔫 {e.Player.Name}{(e.IsHeadshot?" HS":"")}{(e.IsAce?" ACE":"")}"); _gsl.KillFeed += e => Console.WriteLine($" ☠ {e.Killer.Name} → {e.Victim.Name} [{e.Weapon.Name}]"); _gsl.RoundStarted += e => Console.WriteLine($"--- Round {e.Round} ---"); _gsl.RoundConcluded += e => Console.WriteLine($"✔ {e.WinningTeam} wins round {e.Round} ({e.RoundConclusionReason})"); _gsl.Gameover += _ => Console.WriteLine("=== GAME OVER ==="); _gsl.PlayerConnected += e => Console.WriteLine($"+ {e.Value.Name} connected"); _gsl.PlayerDisconnected += e => Console.WriteLine($"- {e.Value.Name} disconnected"); if (!_gsl.Start()) { Console.Error.WriteLine("Failed to start listener. Run as Administrator?"); return; } Console.WriteLine($"Listening on {_gsl.URI} — press ESC to quit."); while (Console.ReadKey(true).Key != ConsoleKey.Escape) Thread.Sleep(100); _gsl.Dispose(); } } ``` -------------------------------- ### Start GameStateListener Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Call the Start() method to begin capturing HTTP POST requests. It returns True on success and False on failure, often due to insufficient permissions or port conflicts. ```C# if (!gsl.Start()) { // GameStateListener could not start. } // GameStateListener started and is listening for Game State requests. ``` -------------------------------- ### GameStateListener Constructor (port) Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Creates a listener bound to `http://localhost:/`. The port integer overload is the simplest way to get started. ```APIDOC ## GameStateListener Constructor (port) Creates a listener bound to `http://localhost:/`. The port integer overload is the simplest way to get started. ```csharp using CounterStrike2GSI; // Bind to http://localhost:3000/ GameStateListener gsl = new GameStateListener(3000); ``` ``` -------------------------------- ### Example Game State Integration Configuration Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md An example of a Game State Integration configuration file. This file defines the data points the game will send to your application. ```json "Example Integration Configuration" { "uri" "http://localhost:3000/" "timeout" "5.0" "buffer" "0.1" "throttle" "0.1" "heartbeat" "10.0" "data" { "provider" "1" "tournamentdraft" "1" "map" "1" "map_round_wins" "1" "round" "1" "player_id" "1" "player_state" "1" "player_weapons" "1" "player_match_stats" "1" "player_position" "1" "phase_countdowns" "1" "allplayers_id" "1" "allplayers_state" "1" "allplayers_match_stats" "1" "allplayers_weapons" "1" "allplayers_position" "1" "allgrenades" "1" "bomb" "1" } } ``` -------------------------------- ### Initialize GameStateListener with Port Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Creates a listener bound to http://localhost:/. Use the integer overload for the simplest setup. ```csharp using CounterStrike2GSI; // Bind to http://localhost:3000/ GameStateListener gsl = new GameStateListener(3000); ``` -------------------------------- ### Manage GameStateListener Lifecycle Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Starts the background HTTP listener thread. `Start()` returns `false` if the port is in use or permissions are insufficient. `Stop()` and `Dispose()` manage thread exit and resource release. ```csharp using CounterStrike2GSI; GameStateListener gsl = new GameStateListener(3000); gsl.GenerateGSIConfigFile("MyApp"); if (!gsl.Start()) { Console.Error.WriteLine("Failed to start – try running as Administrator."); return; } Console.WriteLine($"Listening on {gsl.URI} (port {gsl.Port}), running={gsl.Running}"); // ... application work ... gsl.Stop(); gsl.Dispose(); // or: using var gsl = new GameStateListener(3000); ``` -------------------------------- ### Handle Kill Feed Events in C# Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Subscribe to the KillFeed event to get details about each kill in the game, including killer, victim, weapon, and headshot status. Requires GameStateListener to be started. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; GameStateListener gsl = new GameStateListener(3000); gsl.KillFeed += e => { string hs = e.IsHeadshot ? " (HS)" : ""; Console.WriteLine($"KILLFEED: {e.Killer.Name} [{e.Killer.Team}] → {e.Victim.Name} [{e.Victim.Team}] with {e.Weapon.Name}{hs}"); // Output: KILLFEED: s1mple [CT] → NiKo [T] with weapon_awp (HS) }; gsl.Start(); ``` -------------------------------- ### GenerateGSIConfigFile Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Auto-locates the CS2 installation via Steam registry and writes a fully-populated `gamestate_integration_.cfg` file into the game's `cfg/` directory. Returns `true` on success. ```APIDOC ## GenerateGSIConfigFile Auto-locates the CS2 installation via Steam registry and writes a fully-populated `gamestate_integration_.cfg` file into the game's `cfg/` directory. Returns `true` on success. ```csharp using CounterStrike2GSI; GameStateListener gsl = new GameStateListener(3000); if (!gsl.GenerateGSIConfigFile("MyOverlay")) { Console.WriteLine("Could not write GSI config – is CS2 installed via Steam?"); } // Writes: /game/csgo/cfg/gamestate_integration_MyOverlay.cfg // Config enables: provider, map, round, player, allplayers, allgrenades, bomb, etc. ``` ``` -------------------------------- ### Start / Stop / Dispose Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Starts the background HTTP listener thread. Returns `false` if the port is already in use or permissions are insufficient. `Stop()` signals the thread to exit; `Dispose()` also releases the `HttpListener` and `AutoResetEvent`. ```APIDOC ## Start / Stop / Dispose Starts the background HTTP listener thread. Returns `false` if the port is already in use or permissions are insufficient. `Stop()` signals the thread to exit; `Dispose()` also releases the `HttpListener` and `AutoResetEvent`. ```csharp using CounterStrike2GSI; GameStateListener gsl = new GameStateListener(3000); gsl.GenerateGSIConfigFile("MyApp"); if (!gsl.Start()) { Console.Error.WriteLine("Failed to start – try running as Administrator."); return; } Console.WriteLine($"Listening on {gsl.URI} (port {gsl.Port}), running={gsl.Running}"); // ... application work ... gsl.Stop(); gsl.Dispose(); // or: using var gsl = new GameStateListener(3000); ``` ``` -------------------------------- ### Create GSI Configuration File Statically Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Use the static CS2GSIFile.CreateFile method to generate a GSI configuration file without instantiating GameStateListener. This is useful for initial setup. It can accept either a port number or an explicit URI. ```csharp using CounterStrike2GSI; // Using a port number bool ok1 = CS2GSIFile.CreateFile("StreamWidget", 3000); Console.WriteLine(ok1 ? "Config written." : "Could not write config."); // Using an explicit URI bool ok2 = CS2GSIFile.CreateFile("StreamWidget", "http://localhost:3000/"); Console.WriteLine(ok2 ? "Config written." : "Could not write config."); // Writes: /game/csgo/cfg/gamestate_integration_StreamWidget.cfg ``` -------------------------------- ### Get Currently Active Weapon Information Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Use the GetActiveWeapon() method on a Player object to retrieve details about the currently equipped or reloading weapon. This method returns an empty Weapon object if no weapon is active. The example also iterates through all weapons a player possesses. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.NewGameState += gs => { Weapon active = gs.Player.GetActiveWeapon(); // WeaponType: Knife, Pistol, Rifle, SniperRifle, SubmachineGun, Shotgun, MachineGun, Grenade, C4, ... // WeaponState: Active, Reloading, Holstered if (active.Type != WeaponType.Undefined) { Console.WriteLine($"Active: {active.Name} ({active.Type}) State={active.State}"); Console.WriteLine($" Ammo clip: {active.AmmoClip}/{active.AmmoClipMax} Reserve: {active.AmmoReserve}"); Console.WriteLine($" Skin: {active.PaintKit}"); } // Iterate all weapons foreach (Weapon w in gs.Player.Weapons) Console.WriteLine($" {w.State,-10} {w.Name} ({w.Type})"); }; gsl.Start(); ``` -------------------------------- ### Handle Player Events in C# Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Subscribe to player-related events to track changes in health, armor, money, weapons, and kills. Ensure GameStateListener is initialized and started. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; GameStateListener gsl = new GameStateListener(3000); gsl.PlayerTookDamage += e => Console.WriteLine($"{e.Player.Name}: {e.Previous}→{e.New} HP (-{e.Previous - e.New})"); gsl.PlayerDied += e => Console.WriteLine($"{e.Player.Name} died."); gsl.PlayerRespawned += e => Console.WriteLine($"{e.Player.Name} respawned ({e.New} HP)."); gsl.PlayerArmorChanged += e => Console.WriteLine($"{e.Player.Name} armor: {e.Previous}→{e.New}"); gsl.PlayerHelmetChanged += e => Console.WriteLine($"{e.Player.Name} helmet: {e.New}"); gsl.PlayerMoneyAmountChanged += e => Console.WriteLine($"{e.Player.Name} money: ${e.Previous}→${e.New}"); gsl.PlayerDefusekitChanged += e => Console.WriteLine($"{e.Player.Name} defuse kit: {e.New}"); gsl.PlayerGotKill += e => { string hs = e.IsHeadshot ? " [HEADSHOT]" : ""; string ace = e.IsAce ? " [ACE!]" : ""; Console.WriteLine($"{e.Player.Name} killed with {e.Weapon.Name}{hs}{ace}"); }; gsl.PlayerWeaponsPickedUp += e => { Console.WriteLine($"{e.Player.Name} picked up: {string.Join(", ", e.Weapons.Select(w => w.Name))}"); }; gsl.PlayerWeaponsDropped += e => { Console.WriteLine($"{e.Player.Name} dropped: {string.Join(", ", e.Weapons.Select(w => w.Name))}"); }; gsl.PlayerActiveWeaponChanged += e => Console.WriteLine($"{e.Player.Name}: active weapon {e.Previous.Name} → {e.New.Name}"); gsl.PlayerKillsChanged += e => Console.WriteLine($"{e.Player.Name} kills: {e.New}"); gsl.PlayerDeathsChanged += e => Console.WriteLine($"{e.Player.Name} deaths: {e.New}"); gsl.PlayerMVPsChanged += e => Console.WriteLine($"{e.Player.Name} MVPs: {e.New}"); gsl.Start(); ``` -------------------------------- ### Generate GSI Configuration File Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Automatically generates a `gamestate_integration_.cfg` file in the CS2 `cfg/` directory. Returns `true` on success. Ensure CS2 is installed via Steam for auto-location. ```csharp using CounterStrike2GSI; GameStateListener gsl = new GameStateListener(3000); if (!gsl.GenerateGSIConfigFile("MyOverlay")) { Console.WriteLine("Could not write GSI config – is CS2 installed via Steam?"); } // Writes: /game/csgo/cfg/gamestate_integration_MyOverlay.cfg // Config enables: provider, map, round, player, allplayers, allgrenades, bomb, etc. ``` -------------------------------- ### Listen for Player Connection/Disconnection and Updates (Spectator) Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Subscribe to PlayerConnected, PlayerDisconnected, and AllPlayersUpdated events to track player status and data while spectating. Ensure GameStateListener is started. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.PlayerConnected += e => Console.WriteLine($"+ {e.Value.Name} ({e.Value.SteamID}) joined as {e.Value.Team}"); gsl.PlayerDisconnected += e => Console.WriteLine($"- {e.Value.Name} ({e.Value.SteamID}) left"); gsl.AllPlayersUpdated += e => { // e.New is AllPlayers : NodeMap foreach (var kvp in e.New) { Player p = kvp.Value; Console.WriteLine($" [{p.Team}] {p.Name,-20} HP={p.State.Health,3} K={p.MatchStats.Kills} D={p.MatchStats.Deaths} A={p.MatchStats.Assists}"); } }; gsl.Start(); ``` -------------------------------- ### Handle Map and Round Events in C# Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Subscribe to events related to the game's flow, such as round start/end, score changes, map phases, and match status. Ensure GameStateListener is initialized and started. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.RoundStarted += e => Console.WriteLine($"Round {e.Round} started. First={e.IsFirstRound}"); gsl.RoundConcluded += e => { // RoundConclusion: T_Win_Elimination, T_Win_Bomb, CT_Win_Defuse, CT_Win_Elimination, etc. Console.WriteLine($"Round {e.Round}: {e.WinningTeam} wins ({e.RoundConclusionReason}). Last={e.IsLastRound}"); }; gsl.TeamScoreChanged += e => Console.WriteLine($"{e.Team} score: {e.Previous} → {e.New}"); gsl.TeamRemainingTimeoutsChanged += e => Console.WriteLine($"{e.Team} timeouts left: {e.New}"); gsl.WarmupStarted += e => Console.WriteLine("Warmup started."); gsl.WarmupOver += e => Console.WriteLine("Warmup over."); gsl.FreezetimeStarted += e => Console.WriteLine("Freezetime started."); gsl.FreezetimeOver += e => Console.WriteLine("Freezetime over – GO GO GO!"); gsl.IntermissionStarted += e => Console.WriteLine("Half-time intermission."); gsl.IntermissionOver += e => Console.WriteLine("Second half starting."); gsl.MatchStarted += e => Console.WriteLine("Match started (or resumed)."); gsl.Gameover += e => Console.WriteLine("Game over!"); gsl.TimeoutStarted += e => Console.WriteLine($"{e.Team} timeout started."); gsl.TimeoutOver += e => Console.WriteLine($"{e.Team} timeout ended."); gsl.MapPhaseChanged += e => Console.WriteLine($"Map phase: {e.Previous} → {e.New}"); gsl.RoundPhaseUpdated += e => Console.WriteLine($"Round phase: {e.Previous} → {e.New}"); gsl.GamemodeChanged += e => Console.WriteLine($"Game mode: {e.Previous} → {e.New}"); gsl.LevelChanged += e => Console.WriteLine($"Map: {e.Previous} → {e.New}"); // Round victory/loss per team gsl.TeamRoundVictory += e => Console.WriteLine($"{e.Team} won round #{e.Value}"); gsl.TeamRoundLoss += e => Console.WriteLine($"{e.Team} lost round #{e.Value}"); gsl.Start(); ``` -------------------------------- ### Track Grenade Lifecycle Events (Spectator) Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Utilize NewGrenade, GrenadeUpdated, and ExpiredGrenade events to monitor grenades. Each event provides specific details about the grenade's state and lifecycle. Requires GameStateListener to be started. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.NewGrenade += e => { Grenade g = e.Value; // GrenadeType: Smoke, Decoy, Firebomb, Inferno, Flashbang, Frag Console.WriteLine($"NEW grenade [{e.EntityID}]: {g.Type} by owner={g.Owner} pos={g.Position}"); }; gsl.GrenadeUpdated += e => { if (e.New.Type == GrenadeType.Inferno && e.New.Flames.Count > e.Previous.Flames.Count) Console.WriteLine($"Molotov [{e.EntityID}] spreading – {e.New.Flames.Count} flames"); }; gsl.ExpiredGrenade += e => { Console.WriteLine($"Grenade [{e.EntityID}] ({e.Value.Type}) expired after {e.Value.Lifetime:F1}s"); }; gsl.Start(); ``` -------------------------------- ### Initialize GameStateListener with Custom URI Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Create an instance of GameStateListener specifying a custom URI, including the host and port. ```C# GameStateListener gsl = new GameStateListener("http://127.0.0.1:1234/"); ``` -------------------------------- ### Initialize GameStateListener with Custom Port Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Create an instance of GameStateListener specifying a custom port for communication. ```C# GameStateListener gsl = new GameStateListener(3000); //http://localhost:3000/ ``` -------------------------------- ### Initialize GameStateListener with URI Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Creates a listener bound to an explicit URI. Use this for non-localhost addresses or custom paths, which may require administrator privileges. ```csharp using CounterStrike2GSI; // Bind to a specific IP/port GameStateListener gsl = new GameStateListener("http://192.168.1.10:4000/"); // Throws ArgumentException if the URI format is invalid ``` -------------------------------- ### GameStateListener Constructor (URI) Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Creates a listener bound to an explicit URI. Use this when you need to listen on a non-localhost address (requires administrator privileges) or a custom path. ```APIDOC ## GameStateListener Constructor (URI) Creates a listener bound to an explicit URI. Use this when you need to listen on a non-localhost address (requires administrator privileges) or a custom path. ```csharp using CounterStrike2GSI; // Bind to a specific IP/port GameStateListener gsl = new GameStateListener("http://192.168.1.10:4000/"); // Throws ArgumentException if the URI format is invalid ``` ``` -------------------------------- ### Generate Game State Integration Configuration File Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Automatically generate the necessary configuration file for Game State Integration. This function requires the name of your application and will attempt to locate the game directory. ```C# if (!gsl.GenerateGSIConfigFile("Example")) { Console.WriteLine("Could not generate GSI configuration file."); } ``` -------------------------------- ### Handle Null/Default Values in GameState Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Demonstrates how the library provides safe defaults for missing fields in the GameState. Numeric fields default to -1, strings to "", enums to Undefined, and booleans to false. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.NewGameState += gs => { // Numeric defaults = -1 int hp = gs.Player.State.Health; // -1 when player block absent int money = gs.Player.State.Money; // -1 when not in payload float cd = gs.Bomb.Countdown; // -1f when bomb block absent // String default = "" string name = gs.Player.Name; // "" when absent string bombCarrier = gs.Bomb.Player; // "" when bomb not carried // Enum default = Undefined (-1) BombState bs = gs.Round.BombState; // BombState.Undefined PlayerTeam team = gs.Player.State.Team; // PlayerTeam.Undefined GameMode mode = gs.Map.Mode; // GameMode.Undefined // Bool default = false bool helmet = gs.Player.State.HasHelmet; // false when absent Console.WriteLine($"HP={hp} Money={money} Team={team} BombState={bs} Mode={mode}"); }; gsl.Start(); ``` -------------------------------- ### Listen for New Game State Updates Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Subscribe to the NewGameState event to receive the complete parsed GameState object on every HTTP POST from CS2. This is useful for accessing player, map, round, and bomb information. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.Nodes; GameStateListener gsl = new GameStateListener(3000); gsl.NewGameState += OnNewGameState; gsl.Start(); void OnNewGameState(GameState gs) { // Player info (local player or spectated player) Player p = gs.Player; Console.WriteLine($"Player : {p.Name} ({p.SteamID}) Team={p.Team} Activity={p.Activity}"); Console.WriteLine($" Health={p.State.Health} Armor={p.State.Armor} Helmet={p.State.HasHelmet}"); Console.WriteLine($" Money=${p.State.Money} RoundKills={p.State.RoundKills} Damage={p.State.RoundTotalDamage}"); // Active weapon Weapon w = p.GetActiveWeapon(); Console.WriteLine($" Active weapon: {w.Name} ({w.Type}) Ammo={w.AmmoClip}/{w.AmmoClipMax}+{w.AmmoReserve}"); // Map Console.WriteLine($"Map : {gs.Map.Name} mode={gs.Map.Mode} round={gs.Map.Round} phase={gs.Map.Phase}"); Console.WriteLine($" CT score={gs.Map.CTStatistics.Score} T score={gs.Map.TStatistics.Score}"); // Round Console.WriteLine($"Round: phase={gs.Round.Phase} bombState={gs.Round.BombState} winner={gs.Round.WinningTeam}"); // Phase countdown (spectator only) Console.WriteLine($"Phase ends in: {gs.PhaseCountdowns.PhaseEndTime:F1}s"); // Bomb (spectator only) Bomb b = gs.Bomb; Console.WriteLine($"Bomb : {b.State} countdown={b.Countdown:F1}s carrier={b.Player}"); // Previous state comparison GameState prev = gs.Previously; if (prev.Player.State.Health != p.State.Health) Console.WriteLine($" Health changed from {prev.Player.State.Health} → {p.State.Health}"); } ``` -------------------------------- ### Subscribe to Granular Bomb Events Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Register handlers for specific bomb lifecycle events such as planting, defusing, dropping, and exploding. This allows for fine-grained control and reaction to bomb-related actions. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; GameStateListener gsl = new GameStateListener(3000); gsl.BombPlanting += e => Console.WriteLine($"{e.Player.Name} is planting the bomb!"); gsl.BombPlanted += e => Console.WriteLine("Bomb PLANTED – defuse it!"); gsl.BombDefusing += e => Console.WriteLine($"{e.Player.Name} is defusing. Kit={e.Player.State.HasDefuseKit}"); gsl.BombDefused += e => Console.WriteLine("Bomb DEFUSED!"); gsl.BombExploded += e => Console.WriteLine("Bomb EXPLODED!"); gsl.BombDropped += e => Console.WriteLine("Bomb dropped."); gsl.BombPickedup += e => Console.WriteLine($"{e.Player.Name} picked up the bomb."); gsl.BombStateUpdated += e => Console.WriteLine($"Bomb state: {e.Previous} → {e.New}"); gsl.Start(); ``` -------------------------------- ### Subscribe to New Game State Events Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Subscribe to the NewGameState event to receive updates on the overall game state. A handler function is required to process the received GameState object. ```C# gsl.NewGameState += OnNewGameState; void OnNewGameState(GameState gs) { // Read information from the game state. } ``` -------------------------------- ### Handle All Game Events with Pattern Matching Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt Use the GameEvent event to catch all CS2GameEvent subclasses and handle them using C# pattern matching. This is efficient for managing multiple event types in a single handler. ```csharp using CounterStrike2GSI; using CounterStrike2GSI.EventMessages; GameStateListener gsl = new GameStateListener(3000); gsl.GameEvent += OnGameEvent; gsl.Start(); void OnGameEvent(CS2GameEvent e) { switch (e) { case PlayerTookDamage dmg: int amount = dmg.Previous - dmg.New; Console.WriteLine($"{dmg.Player.Name} took {amount} damage ({dmg.Previous}→{dmg.New} HP)"); break; case PlayerActiveWeaponChanged wc: Console.WriteLine($"{wc.Player.Name}: {wc.Previous.Name} → {wc.New.Name}"); break; case PlayerDied died: Console.WriteLine($"{died.Player.Name} died (was at {died.Previous} HP)"); break; case PlayerRespawned resp: Console.WriteLine($"{resp.Player.Name} respawned with {resp.New} HP"); break; case BombStateUpdated bomb: Console.WriteLine($"Bomb state changed: {bomb.Previous} → {bomb.New}"); break; case RoundStarted rs: Console.WriteLine($"Round {rs.Round} started. First={rs.IsFirstRound} Last={rs.IsLastRound}"); break; case RoundConcluded rc: Console.WriteLine($"Round {rc.Round} won by {rc.WinningTeam} via {rc.RoundConclusionReason}"); break; } } ``` -------------------------------- ### Subscribe to Specific Game Events Source: https://github.com/antonpup/counterstrike2gsi/blob/master/README.md Subscribe to specific game events like BombStateUpdated, PlayerWeaponsPickedUp, or RoundConcluded to handle particular in-game occurrences. You can also subscribe to the general GameEvent for all events. ```C# gsl.GameEvent += OnGameEvent; // Will fire on every GameEvent gsl.BombStateUpdated += OnBombStateUpdated; // Will only fire on BombStateUpdated events. gsl.PlayerWeaponsPickedUp += OnPlayerWeaponsPickedUp; // Will only fire on PlayerWeaponsPickedUp events. gsl.RoundConcluded += OnRoundConcluded; // Will only fire on RoundConcluded events. void OnGameEvent(CS2GameEvent game_event) { // Read information from the game event. if (game_event is PlayerTookDamage player_took_damage) { Console.WriteLine($"The player {player_took_damage.Player.Name} took {player_took_damage.Previous - player_took_damage.New} damage!"); } else if (game_event is PlayerActiveWeaponChanged active_weapon_changed) { Console.WriteLine($"The player {active_weapon_changed.Player.Name} changed their active weapon to {active_weapon_changed.New.Name} from {active_weapon_changed.Previous.Name}."); } } void OnBombStateUpdated(BombStateUpdated game_event) { Console.WriteLine($"The bomb is now {game_event.New}."); } void OnPlayerWeaponsPickedUp(PlayerWeaponsPickedUp game_event) { Console.WriteLine($"The player {game_event.Player.Name} picked up the following weapons:"); foreach (var weapon in game_event.Weapons) { Console.WriteLine($"\t{weapon.Name}"); } } void OnRoundConcluded(RoundConcluded game_event) { Console.WriteLine($"Round {game_event.Round} concluded by {game_event.WinningTeam} for reason: {game_event.RoundConclusionReason}"); } ``` -------------------------------- ### Access Previous Game State Data Source: https://context7.com/antonpup/counterstrike2gsi/llms.txt The GameState.Previously property provides access to the prior game state snapshot as included in the CS2 JSON payload. This allows for direct comparison of values within the same payload. It can be used to track changes like health deltas or round win history. ```csharp using CounterStrike2GSI; GameStateListener gsl = new GameStateListener(3000); gsl.NewGameState += gs => { // Compare current vs previously (as embedded in the CS2 payload) int prevHP = gs.Previously.Player.State.Health; // -1 if not in payload int currHP = gs.Player.State.Health; if (prevHP != -1 && currHP != prevHP) Console.WriteLine($"Health delta (from payload): {prevHP} → {currHP}"); // Round wins history foreach (var kv in gs.Map.RoundWins) Console.WriteLine($" Round {kv.Key}: {kv.Value}"); // e.g. Round 1: CT_Win_Elimination }; gsl.Start(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.