cs2log

package module
v0.0.0-...-967583d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2025 License: MIT Imports: 8 Imported by: 0

README

cs2-log

Go package for parsing cs2 server logfiles. It exports types for cs2 logfiles, their regular expressions, a function for parsing and a function for converting to non-html-escaped JSON.

Fork Features

This is an enhanced fork of the original janstuemmel/cs2-log with:

  • 30+ additional event types for comprehensive CS2 log parsing
  • Enhanced parsing functions (ParseEnhanced, ParseOrdered)
  • Improved pattern matching for CS2's [U:1:xxx] Steam ID format
  • Support for corrupted/malformed log entries
  • Custom event categories (match management, statistics, etc.)

Documentation

Usage

For more examples look at the tests and the command-line utility in examples folder. Have also a look at godoc.

Basic Usage
package main

import (
	"fmt"

	cs2log "github.com/noueii/cs2-log"
)

func main() {

	var msg cs2log.Message

	// a line from a server logfile
	line := `L 11/05/2018 - 15:44:36: "Player<12><[U:1:29384012]><CT>" purchased "m4a1"`

	// parse into Message (standard parsing)
	msg, err := cs2log.Parse(line)
	
	// OR use enhanced parsing for custom events
	msg, err = cs2log.ParseEnhanced(line)
	
	// OR use ordered parsing for priority matching
	msg, err = cs2log.ParseOrdered(line)

	if err != nil {
		panic(err)
	}

	fmt.Println(msg.GetType(), msg.GetTime().String())

	// cast Message interface to PlayerPurchase type
	playerPurchase, ok := msg.(cs2log.PlayerPurchase)

	if ok != true {
		panic("casting failed")
	}

	fmt.Println(playerPurchase.Player.SteamID, playerPurchase.Item)

	// get json non-htmlescaped
	jsn := cs2log.ToJSON(msg)

	fmt.Println(jsn)
}

Example JSON output:

{
  "time": "2018-11-05T15:44:36Z",
  "type": "PlayerPurchase",
  "player": {
    "name": "Player",
    "id": 12,
    "steam_id": "[U:1:29384012]",
    "side": "CT"
  },
  "item": "m4a1"
}
Parsing Functions

The library provides multiple parsing functions:

Single-Line Parsing
Parse(line string) (Message, error)

Standard parsing using default CS2 event patterns. Use this for basic CS2 log parsing.

ParseEnhanced(line string) (Message, error)

Enhanced parsing that includes both default patterns and 30+ custom event types. Recommended for comprehensive log analysis.

ParseOrdered(line string) (Message, error)

Ordered parsing that respects pattern priority (e.g., chat commands before regular chat). Use when pattern matching order matters.

ParseLines(lines []string) ([]Message, []error)

Batch parsing that takes multiple log lines and returns all parsed events. Automatically handles multi-line JSON statistics blocks. This is the recommended approach for parsing log files.

ParseLinesOrdered(lines []string) ([]Message, []error)

Batch parsing with ordered pattern matching for priority-sensitive parsing.

ParseLinesEnhanced(lines []string) ([]Message, []error)

Batch parsing with enhanced pattern support for all custom event types.

Custom Events

This fork adds support for many additional events:

  • Player Events: PlayerLeftBuyzone, PlayerValidated, PlayerJoinedTeam, PlayerAccolade
  • Match Events: MatchStatus, RoundOfficiallyEnded, BeginNewMatchReady
  • Server Events: ServerCvar, ServerSay, LoadingMap, StartedMap, Rcon
  • Combat Events: PlayerFlashAssist, PlayerKilledOther
  • Statistics: RoundStats (JSON format), PlayerAccolade
  • Chat: ChatCommand (for commands like .ready, !gg)

See EVENTS.md for complete documentation of all supported events.

Documentation

Overview

Package cs2log provides utilities for parsing a counter-strike 2 server logfile. It exports types for cs2 logfiles, their regular expressions, a function for parsing and a function for converting to non-html-escaped JSON.

Look at the examples for Parse and ToJSON for usage instructions.

Index

Examples

Constants

View Source
const (
	// ServerMessagePattern regular expression
	ServerMessagePattern = `server_message: "(\w+)"`
	// FreezTimeStartPattern regular expression
	FreezTimeStartPattern = `Starting Freeze period`
	// WorldMatchStartPattern regular expression
	WorldMatchStartPattern = `World triggered "Match_Start" on "(\w+)"`
	// WorldRoundStartPattern regular expression
	WorldRoundStartPattern = `World triggered "Round_Start"`
	// WorldRoundRestartPattern regular expression
	WorldRoundRestartPattern = `World triggered "Restart_Round_\((\d+)_second\)`
	// WorldRoundEndPattern regular expression
	WorldRoundEndPattern = `World triggered "Round_End"`
	// WorldGameCommencingPattern regular expression
	WorldGameCommencingPattern = `World triggered "Game_Commencing"`
	// TeamScoredPattern regular expression
	TeamScoredPattern = `Team "(CT|TERRORIST)" scored "(\d+)" with "(\d+)" players`
	// TeamNoticePattern regular expression
	TeamNoticePattern = `Team "(CT|TERRORIST)" triggered "(\w+)" \(CT "(\d+)"\) \(T "(\d+)"\)`
	// PlayerConnectedPattern regular expression
	PlayerConnectedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><>" connected, address "(.*)"`
	// PlayerDisconnectedPattern regular expression
	PlayerDisconnectedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT|Unassigned|)>" disconnected \(reason "(.+)"\)`
	// PlayerEnteredPattern regular expression
	PlayerEnteredPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><>" entered the game`
	// PlayerBannedPattern regular expression
	PlayerBannedPattern = `Banid: "(.+)<(\d+)><([\[\]\w:_]+)><\w*>" was banned "([\w. ]+)" by "(\w+)"`
	// PlayerSwitchedPattern regular expression
	PlayerSwitchedPattern = `` /* 126-byte string literal not displayed */
	// PlayerSayPattern regular expression
	PlayerSayPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" say(_team)? "(.*)"`
	// PlayerPurchasePattern regular expression
	PlayerPurchasePattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" purchased "(\w+)"`
	// PlayerKillPattern regular expression
	PlayerKillPattern = `` /* 217-byte string literal not displayed */
	// PlayerKillAssistPattern regular expression
	PlayerKillAssistPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" assisted killing "(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>"`
	// PlayerFlashAssistPattern regular expression
	PlayerFlashAssistPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" flash-assisted killing "(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>"`
	// PlayerAttackPattern regular expression - handles corrupted SteamIDs
	PlayerAttackPattern = `` /* 260-byte string literal not displayed */
	// PlayerKilledBombPattern regular expression
	PlayerKilledBombPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" \[(-?\d+) (-?\d+) (-?\d+)\] was killed by the bomb\.`
	// PlayerKilledSuicidePattern regular expression
	PlayerKilledSuicidePattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" \[(-?\d+) (-?\d+) (-?\d+)\] committed suicide with "(.*)"`
	// PlayerPickedUpPattern regular expression
	PlayerPickedUpPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" picked up "(\w+)"`
	// PlayerDroppedPattern regular expression
	PlayerDroppedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT|Unassigned)>" dropped "(\w+)"`
	// PlayerMoneyChangePattern regular expression - handles both tracked and untracked formats
	PlayerMoneyChangePattern = `` /* 128-byte string literal not displayed */
	// PlayerBombGotPattern regular expression
	PlayerBombGotPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" triggered "Got_The_Bomb"`
	// PlayerBombPlantedPattern regular expression
	PlayerBombPlantedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" triggered "Planted_The_Bomb"`
	// PlayerBombDroppedPattern regular expression
	PlayerBombDroppedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" triggered "Dropped_The_Bomb"`
	// PlayerBombBeginDefusePattern regular expression
	PlayerBombBeginDefusePattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" triggered "Begin_Bomb_Defuse_With(out)?_Kit"`
	// PlayerBombDefusedPattern regular expression
	PlayerBombDefusedPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" triggered "Defused_The_Bomb"`
	// PlayerThrewPattern regular expression
	PlayerThrewPattern = `"(.+)<(\d+)><([\[\]\w:_]+)><(TERRORIST|CT)>" threw (\w+) \[(-?\d+) (-?\d+) (-?\d+)\]( flashbang entindex (\d+))?\)?`
	// PlayerBlindedPattern regular expression - handles any characters in SteamID field and any team
	PlayerBlindedPattern = `"(.+)<(\d+)><([^>]*)><([^>]*)>" blinded for ([\d.]+) by "(.+)<(\d+)><([^>]*)><([^>]*)>" from flashbang entindex (\d+)`
	// ProjectileSpawnedPattern regular expression
	ProjectileSpawnedPattern = `Molotov projectile spawned at (-?\d+\.\d+) (-?\d+\.\d+) (-?\d+\.\d+), velocity (-?\d+\.\d+) (-?\d+\.\d+) (-?\d+\.\d+)`
	// GameOverPattern regular expression
	GameOverPattern = `Game Over: (\w+) (\w+) (\w+) score (\d+):(\d+) after (\d+) min`
)
View Source
const (
	// Buy Zone Events
	PlayerLeftBuyzonePattern = `"(.+?)<(\d+)><(.+?)><(.*?)>" left buyzone with \[(.*?)\]`

	// Validation Events
	PlayerValidatedPattern = `"(.+?)<(\d+)><(.+?)><>" STEAM USERID validated`

	// Achievement/Award Events - handle tabs or commas as delimiters
	PlayerAccoladePattern = `ACCOLADE, (FINAL|ROUND): \{(.+?)\}[,\t]\s*(.+?)<(\d+)>[,\t]\s*VALUE: ([^,\t]+)`

	// Match Status Events
	MatchStatusScorePattern = `MatchStatus: Score: (\d+):(\d+) on map "(.+?)" RoundsPlayed: (-?\d+)`
	TeamPlayingPattern      = `Team playing "(TERRORIST|CT)": (.+)`
	MatchStatusTeamPattern  = `MatchStatus: Team playing "(TERRORIST|CT)": (.+)`

	// Pause Events
	MatchPauseEnabledPattern  = `Match pause is enabled`
	MatchPauseDisabledPattern = `Match pause is disabled`
	MatchUnpausePattern       = `Match unpaused`

	// Debug Events
	GrenadeThrowDebugPattern = `"(.+?)" (sv_throw_\w+) (-?\d+\.?\d*) (-?\d+\.?\d*) (-?\d+\.?\d*) (-?\d+\.?\d*) (-?\d+\.?\d*) (-?\d+\.?\d*)`

	// Server Configuration Events
	ServerCvarPattern = `server_cvar: "(.+?)" "(.+?)"`
	MpCvarPattern     = `"(mp_.+?)" = "(.+?)"`

	// RCON Events
	RconCommandPattern = `rcon from "(.+?)": command "(.+?)"`

	// Map Events
	LoadingMapPattern = `Loading map "(.+?)"`
	StartedMapPattern = `Started map "(.+?)"`

	// Log File Events
	LogFileStartedPattern = `Log file started \(file "(.+?)"\)`
	LogFileClosedPattern  = `Log file closed`

	// Extended Chat Events (commands)
	ChatCommandPattern = `"(.+?)<(\d+)><(.+?)><(.*?)>" say(?:_team)? "\.(\w+)\s*(.*)"`

	// Round Statistics Events
	RoundStatsFieldsPattern = `"fields"\s*:\s*"([^"]+)"`
	RoundStatsPlayerPattern = `"(player_\d+)"\s*:\s*"([^"]+)"`

	// JSON Round Stats markers
	JSONBeginPattern              = `JSON_BEGIN\{`
	JSONEndPattern                = `\}\}JSON_END`
	RoundStatsNamePattern         = `"name"\s*:\s*"round_stats"`
	RoundStatsRoundPattern        = `"round_number"\s*:\s*"(\d+)"`
	RoundStatsScoreTPattern       = `"score_t"\s*:\s*"(\d+)"`
	RoundStatsScoreCTPattern      = `"score_ct"\s*:\s*"(\d+)"`
	RoundStatsMapPattern          = `"map"\s*:\s*"([^"]+)"`
	RoundStatsServerPattern       = `"server"\s*:\s*"([^"]+)"`
	RoundStatsPlayersStartPattern = `"players"\s*:\s*\{`

	// Game Over with details
	GameOverDetailedPattern = `Game Over: (\w+) (.+?) score (\d+):(\d+) after (\d+) min`

	// Triggered Events
	TriggeredEventPattern = `(World|Team ".*?") triggered "(.+?)"`

	// Bomb Events (extended)
	BombBeginPlantPattern     = `"(.+?)<(\d+)><(.+?)><(.*?)>" triggered "Bomb_Begin_Plant"`
	BombPlantedTriggerPattern = `"(.+?)<(\d+)><(.+?)><(.*?)>" triggered "Planted_The_Bomb"`
	BombDefusedTriggerPattern = `"(.+?)<(\d+)><(.+?)><(.*?)>" triggered "Defused_The_Bomb"`

	// Freeze Period
	FreezePeriodStartPattern = `Starting Freeze period`
	FreezePeriodEndPattern   = `World triggered "Round_Freeze_End"`

	// JSON Statistics
	StatsJSONStartPattern  = `JSON_BEGIN\{`
	StatsJSONEndPattern    = `\}\}JSON_END`
	StatsJSONPlayerPattern = `"player_\d+": \{`

	// Warmup Events
	WarmupStartPattern = `World triggered "Warmup_Start"`
	WarmupEndPattern   = `World triggered "Warmup_End"`
)

Custom event patterns

Variables

View Source
var DefaultPatterns = map[*regexp.Regexp]MessageFunc{
	regexp.MustCompile(ServerMessagePattern):         NewServerMessage,
	regexp.MustCompile(FreezTimeStartPattern):        NewFreezTimeStart,
	regexp.MustCompile(WorldMatchStartPattern):       NewWorldMatchStart,
	regexp.MustCompile(WorldRoundStartPattern):       NewWorldRoundStart,
	regexp.MustCompile(WorldRoundRestartPattern):     NewWorldRoundRestart,
	regexp.MustCompile(WorldRoundEndPattern):         NewWorldRoundEnd,
	regexp.MustCompile(WorldGameCommencingPattern):   NewWorldGameCommencing,
	regexp.MustCompile(TeamScoredPattern):            NewTeamScored,
	regexp.MustCompile(TeamNoticePattern):            NewTeamNotice,
	regexp.MustCompile(PlayerConnectedPattern):       NewPlayerConnected,
	regexp.MustCompile(PlayerDisconnectedPattern):    NewPlayerDisconnected,
	regexp.MustCompile(PlayerEnteredPattern):         NewPlayerEntered,
	regexp.MustCompile(PlayerBannedPattern):          NewPlayerBanned,
	regexp.MustCompile(PlayerSwitchedPattern):        NewPlayerSwitched,
	regexp.MustCompile(PlayerSayPattern):             NewPlayerSay,
	regexp.MustCompile(PlayerPurchasePattern):        NewPlayerPurchase,
	regexp.MustCompile(PlayerKillPattern):            NewPlayerKill,
	regexp.MustCompile(PlayerKillAssistPattern):      NewPlayerKillAssist,
	regexp.MustCompile(PlayerFlashAssistPattern):     NewPlayerFlashAssist,
	regexp.MustCompile(PlayerAttackPattern):          NewPlayerAttack,
	regexp.MustCompile(PlayerKilledBombPattern):      NewPlayerKilledBomb,
	regexp.MustCompile(PlayerKilledSuicidePattern):   NewPlayerKilledSuicide,
	regexp.MustCompile(PlayerPickedUpPattern):        NewPlayerPickedUp,
	regexp.MustCompile(PlayerDroppedPattern):         NewPlayerDropped,
	regexp.MustCompile(PlayerMoneyChangePattern):     NewPlayerMoneyChange,
	regexp.MustCompile(PlayerBombGotPattern):         NewPlayerBombGot,
	regexp.MustCompile(PlayerBombPlantedPattern):     NewPlayerBombPlanted,
	regexp.MustCompile(PlayerBombDroppedPattern):     NewPlayerBombDropped,
	regexp.MustCompile(PlayerBombBeginDefusePattern): NewPlayerBombBeginDefuse,
	regexp.MustCompile(PlayerBombDefusedPattern):     NewPlayerBombDefused,
	regexp.MustCompile(PlayerThrewPattern):           NewPlayerThrew,
	regexp.MustCompile(PlayerBlindedPattern):         NewPlayerBlinded,
	regexp.MustCompile(ProjectileSpawnedPattern):     NewProjectileSpawned,
	regexp.MustCompile(GameOverPattern):              NewGameOver,
}
View Source
var ErrorNoMatch = errors.New("no match")

ErrorNoMatch error when pattern is not matching

View Source
var ExtendedPatterns = map[*regexp.Regexp]MessageFunc{

	regexp.MustCompile(PlayerLeftBuyzonePattern): NewPlayerLeftBuyzone,

	regexp.MustCompile(PlayerValidatedPattern): NewPlayerValidated,

	regexp.MustCompile(PlayerAccoladePattern): NewPlayerAccolade,

	regexp.MustCompile(MatchStatusScorePattern): NewMatchStatus,
	regexp.MustCompile(TeamPlayingPattern):      NewTeamPlaying,
	regexp.MustCompile(MatchStatusTeamPattern):  NewTeamPlaying,

	regexp.MustCompile(MatchPauseEnabledPattern):  NewMatchPauseEnabled,
	regexp.MustCompile(MatchPauseDisabledPattern): NewMatchPauseDisabled,
	regexp.MustCompile(MatchUnpausePattern):       NewMatchUnpause,

	regexp.MustCompile(GrenadeThrowDebugPattern): NewGrenadeThrowDebug,

	regexp.MustCompile(ServerCvarPattern): NewServerCvar,
	regexp.MustCompile(MpCvarPattern):     NewServerCvar,

	regexp.MustCompile(RconCommandPattern): NewRconCommand,

	regexp.MustCompile(LoadingMapPattern): NewLoadingMap,
	regexp.MustCompile(StartedMapPattern): NewStartedMap,

	regexp.MustCompile(LogFileStartedPattern): NewLogFileStarted,
	regexp.MustCompile(LogFileClosedPattern):  NewLogFileClosed,

	regexp.MustCompile(RoundStatsFieldsPattern): NewRoundStatsFields,
	regexp.MustCompile(RoundStatsPlayerPattern): NewRoundStatsPlayer,

	regexp.MustCompile(ChatCommandPattern): NewChatCommand,

	regexp.MustCompile(GameOverDetailedPattern): NewGameOverDetailed,

	regexp.MustCompile(TriggeredEventPattern): NewTriggeredEvent,

	regexp.MustCompile(BombBeginPlantPattern):     NewBombBeginPlant,
	regexp.MustCompile(BombPlantedTriggerPattern): NewBombBeginPlant,
	regexp.MustCompile(BombDefusedTriggerPattern): NewBombBeginPlant,

	regexp.MustCompile(FreezePeriodStartPattern): NewFreezePeriodStart,
	regexp.MustCompile(FreezePeriodEndPattern):   NewFreezePeriodEnd,

	regexp.MustCompile(StatsJSONStartPattern): NewStatsJSONStart,
	regexp.MustCompile(StatsJSONEndPattern):   NewStatsJSONEnd,

	regexp.MustCompile(WarmupStartPattern): NewWarmupStart,
	regexp.MustCompile(WarmupEndPattern):   NewWarmupEnd,
}

ExtendedPatterns contains all custom patterns

View Source
var LogLinePattern = regexp.MustCompile(`(\d{2}\/\d{2}\/\d{4} - \d{2}:\d{2}:\d{2}\.\d{3}): (.*)`)

LogLinePattern is the regular expression to capture a line of a logfile Format: MM/DD/YYYY - HH:MM:SS.mmm: message

Functions

func CombinedPatterns

func CombinedPatterns() map[*regexp.Regexp]MessageFunc

CombinedPatterns merges DefaultPatterns with ExtendedPatterns Returns patterns in priority order (specific patterns before general ones)

func ToJSON

func ToJSON(m Message) string

ToJSON marshals messages to JSON without escaping html

Example
package main

import (
	"fmt"

	cs2log "github.com/noueii/cs2-log"
)

func main() {

	// parse Message (from debug/good_logs/sv1/combined_logs.log)
	msg, _ := cs2log.Parse(`08/29/2025 - 10:26:49.000: "ragga<6><[U:1:109933575]><TERRORIST>" purchased "ak47"`)

	// cast Message interface type to PlayerPurchase type
	playerPurchase, _ := msg.(cs2log.PlayerPurchase)

	fmt.Println(playerPurchase.Player.SteamID)
	fmt.Println(playerPurchase.Item)

	// get json non-html-escaped
	jsn := cs2log.ToJSON(msg)

	fmt.Println(jsn)
}
Output:
[U:1:109933575]
ak47
{"time":"2025-08-29T10:26:49Z","type":"PlayerPurchase","player":{"name":"ragga","id":6,"steam_id":"[U:1:109933575]","side":"TERRORIST"},"item":"ak47"}

Types

type BombEvent

type BombEvent struct {
	Meta
	Player   Player   `json:"player"`
	Action   string   `json:"action"` // "begin_plant", "abort_plant", etc.
	Site     string   `json:"site,omitempty"`
	Position Position `json:"position,omitempty"`
}

BombEvent for additional bomb-related triggers

type ChatCommand

type ChatCommand struct {
	Meta
	Player  Player `json:"player"`
	Command string `json:"command"` // The command without the dot (e.g., "pause", "ready")
	Args    string `json:"args,omitempty"`
	Text    string `json:"text"` // Full text including the command
}

ChatCommand is received when a player uses a chat command

type Equation

type Equation struct {
	A      int `json:"a"`
	B      int `json:"b"`
	Result int `json:"result"`
}

Equation holds the parameters and result of a money change equation in the form A + B = Result

type FreezTimeStart

type FreezTimeStart struct{ Meta }

FreezTimeStart is received before each round

type FreezePeriod

type FreezePeriod struct {
	Meta
	Action string `json:"action"` // "start", "end"
}

FreezePeriod for freeze period events

type GameOver

type GameOver struct {
	Meta
	Mode     string `json:"mode"`
	MapGroup string `json:"map_group"`
	Map      string `json:"map"`
	ScoreCT  int    `json:"score_ct"`
	ScoreT   int    `json:"score_t"`
	Duration int    `json:"duration"`
}

GameOver is received when a team won and the game ends

type GameOverDetailed

type GameOverDetailed struct {
	Meta
	Mode     string `json:"mode"` // "competitive", "casual", etc.
	Map      string `json:"map"`
	ScoreCT  int    `json:"score_ct"`
	ScoreT   int    `json:"score_t"`
	Duration int    `json:"duration"` // in minutes
}

GameOverDetailed provides more detail about game ending

type GrenadeThrowDebug

type GrenadeThrowDebug struct {
	Meta
	Player       Player        `json:"player"`
	GrenadeType  string        `json:"grenade_type"` // "molotov", "smokegrenade", "flashgrenade", "hegrenade"
	Position     PositionFloat `json:"position"`
	Velocity     Velocity      `json:"velocity"`
	DebugCommand string        `json:"debug_command"` // Full sv_throw command
}

GrenadeThrowDebug is received for grenade trajectory debug data

type JSONStatistics

type JSONStatistics struct {
	Meta
	Name        string                      `json:"name"` // e.g., "round_stats"
	RoundNumber int                         `json:"round_number"`
	ScoreT      int                         `json:"score_t"`
	ScoreCT     int                         `json:"score_ct"`
	Map         string                      `json:"map"`
	Server      string                      `json:"server"`
	Fields      []string                    `json:"fields"`   // List of field names
	Players     map[string]PlayerStatistics `json:"players"`  // Map of player_id to stats
	RawJSON     string                      `json:"raw_json"` // Complete raw JSON for custom processing
}

JSONStatistics represents a complete JSON statistics block from the logs

func (JSONStatistics) GetTime

func (j JSONStatistics) GetTime() time.Time

GetTime returns the timestamp of the JSONStatistics message

func (JSONStatistics) GetType

func (j JSONStatistics) GetType() string

GetType returns the type of the JSONStatistics message

type LoadingMap

type LoadingMap struct {
	Meta
	Map string `json:"map"`
}

LoadingMap is received when server starts loading a map

type LogFile

type LogFile struct {
	Meta
	Action   string `json:"action"` // "started", "closed"
	Filename string `json:"filename,omitempty"`
}

LogFile is received for log file events

type MatchPause

type MatchPause struct {
	Meta
	Action string `json:"action"` // "enabled", "disabled", "unpaused"
	Reason string `json:"reason,omitempty"`
}

MatchPause is received when match is paused/unpaused

type MatchStatus

type MatchStatus struct {
	Meta
	ScoreCT      int    `json:"score_ct"`
	ScoreT       int    `json:"score_t"`
	Map          string `json:"map"`
	RoundsPlayed int    `json:"rounds_played"`
}

MatchStatus is received for match score updates

type MatchStatusTeam

type MatchStatusTeam struct {
	Meta
	Side     string `json:"side"`
	TeamName string `json:"team_name"`
}

MatchStatusTeam is received when team assignments are shown

type Message

type Message interface {
	GetType() string
	GetTime() time.Time
}

Message is the interface for all messages

func NewBombBeginPlant

func NewBombBeginPlant(ti time.Time, r []string) Message

func NewChatCommand

func NewChatCommand(ti time.Time, r []string) Message

func NewFreezTimeStart

func NewFreezTimeStart(ti time.Time, r []string) Message

func NewFreezePeriodEnd

func NewFreezePeriodEnd(ti time.Time, r []string) Message

func NewFreezePeriodStart

func NewFreezePeriodStart(ti time.Time, r []string) Message

func NewGameOver

func NewGameOver(ti time.Time, r []string) Message

func NewGameOverDetailed

func NewGameOverDetailed(ti time.Time, r []string) Message

func NewGrenadeThrowDebug

func NewGrenadeThrowDebug(ti time.Time, r []string) Message

func NewJSONBegin

func NewJSONBegin(ti time.Time, r []string) Message

func NewJSONEnd

func NewJSONEnd(ti time.Time, r []string) Message

func NewLoadingMap

func NewLoadingMap(ti time.Time, r []string) Message

func NewLogFileClosed

func NewLogFileClosed(ti time.Time, r []string) Message

func NewLogFileStarted

func NewLogFileStarted(ti time.Time, r []string) Message

func NewMatchPause

func NewMatchPause(ti time.Time, action string, reason string) Message

func NewMatchPauseDisabled

func NewMatchPauseDisabled(ti time.Time, r []string) Message

func NewMatchPauseEnabled

func NewMatchPauseEnabled(ti time.Time, r []string) Message

func NewMatchStatus

func NewMatchStatus(ti time.Time, r []string) Message

func NewMatchUnpause

func NewMatchUnpause(ti time.Time, r []string) Message

func NewPlayerAccolade

func NewPlayerAccolade(ti time.Time, r []string) Message

func NewPlayerAttack

func NewPlayerAttack(ti time.Time, r []string) Message

func NewPlayerBanned

func NewPlayerBanned(ti time.Time, r []string) Message

func NewPlayerBlinded

func NewPlayerBlinded(ti time.Time, r []string) Message

func NewPlayerBombBeginDefuse

func NewPlayerBombBeginDefuse(ti time.Time, r []string) Message

func NewPlayerBombDefused

func NewPlayerBombDefused(ti time.Time, r []string) Message

func NewPlayerBombDropped

func NewPlayerBombDropped(ti time.Time, r []string) Message

func NewPlayerBombGot

func NewPlayerBombGot(ti time.Time, r []string) Message

func NewPlayerBombPlanted

func NewPlayerBombPlanted(ti time.Time, r []string) Message

func NewPlayerConnected

func NewPlayerConnected(ti time.Time, r []string) Message

func NewPlayerDisconnected

func NewPlayerDisconnected(ti time.Time, r []string) Message

func NewPlayerDropped

func NewPlayerDropped(ti time.Time, r []string) Message

func NewPlayerEntered

func NewPlayerEntered(ti time.Time, r []string) Message

func NewPlayerFlashAssist

func NewPlayerFlashAssist(ti time.Time, r []string) Message

func NewPlayerKill

func NewPlayerKill(ti time.Time, r []string) Message

func NewPlayerKillAssist

func NewPlayerKillAssist(ti time.Time, r []string) Message

func NewPlayerKilledBomb

func NewPlayerKilledBomb(ti time.Time, r []string) Message

func NewPlayerKilledSuicide

func NewPlayerKilledSuicide(ti time.Time, r []string) Message

func NewPlayerLeftBuyzone

func NewPlayerLeftBuyzone(ti time.Time, r []string) Message

func NewPlayerMoneyChange

func NewPlayerMoneyChange(ti time.Time, r []string) Message

func NewPlayerPickedUp

func NewPlayerPickedUp(ti time.Time, r []string) Message

func NewPlayerPurchase

func NewPlayerPurchase(ti time.Time, r []string) Message

func NewPlayerSay

func NewPlayerSay(ti time.Time, r []string) Message

func NewPlayerSwitched

func NewPlayerSwitched(ti time.Time, r []string) Message

func NewPlayerThrew

func NewPlayerThrew(ti time.Time, r []string) Message

func NewPlayerValidated

func NewPlayerValidated(ti time.Time, r []string) Message

func NewProjectileSpawned

func NewProjectileSpawned(ti time.Time, r []string) Message

func NewRconCommand

func NewRconCommand(ti time.Time, r []string) Message

func NewRoundStatsFields

func NewRoundStatsFields(ti time.Time, r []string) Message

func NewRoundStatsMetadata

func NewRoundStatsMetadata(ti time.Time, r []string) Message

func NewRoundStatsName

func NewRoundStatsName(ti time.Time, r []string) Message

func NewRoundStatsPlayer

func NewRoundStatsPlayer(ti time.Time, r []string) Message

func NewServerCvar

func NewServerCvar(ti time.Time, r []string) Message

func NewServerMessage

func NewServerMessage(ti time.Time, r []string) Message

func NewStartedMap

func NewStartedMap(ti time.Time, r []string) Message

func NewStatsJSON

func NewStatsJSON(ti time.Time, statsType string, data string) Message

Placeholder functions to prevent compilation errors These should not be used and will return Unknown messages

func NewStatsJSONEnd

func NewStatsJSONEnd(ti time.Time, r []string) Message

func NewStatsJSONStart

func NewStatsJSONStart(ti time.Time, r []string) Message

func NewTeamNotice

func NewTeamNotice(ti time.Time, r []string) Message

func NewTeamPlaying

func NewTeamPlaying(ti time.Time, r []string) Message

func NewTeamScored

func NewTeamScored(ti time.Time, r []string) Message

func NewTriggeredEvent

func NewTriggeredEvent(ti time.Time, r []string) Message

func NewUnknown

func NewUnknown(ti time.Time, r []string) Message

func NewWarmupEnd

func NewWarmupEnd(ti time.Time, r []string) Message

func NewWarmupStart

func NewWarmupStart(ti time.Time, r []string) Message

func NewWorldGameCommencing

func NewWorldGameCommencing(ti time.Time, r []string) Message

func NewWorldMatchStart

func NewWorldMatchStart(ti time.Time, r []string) Message

func NewWorldRoundEnd

func NewWorldRoundEnd(ti time.Time, r []string) Message

func NewWorldRoundRestart

func NewWorldRoundRestart(ti time.Time, r []string) Message

func NewWorldRoundStart

func NewWorldRoundStart(ti time.Time, r []string) Message

func Parse

func Parse(line string) (Message, error)

Parse parses a plain log message and returns message type or error if there's no match

Example
package main

import (
	"fmt"

	cs2log "github.com/noueii/cs2-log"
)

func main() {

	var msg cs2log.Message

	// a line from a server logfile (from debug/good_logs/sv1/combined_logs.log)
	line := `08/29/2025 - 10:26:49.000: "ragga<6><[U:1:109933575]><TERRORIST>" purchased "item_assaultsuit"`

	// parse Message
	msg, _ = cs2log.Parse(line)

	fmt.Println(msg.GetType())
	fmt.Println(msg.GetTime().String())
}
Output:
PlayerPurchase
2025-08-29 10:26:49 +0000 UTC

func ParseEnhanced

func ParseEnhanced(line string) (Message, error)

ParseEnhanced parses a log line using both default and extended patterns This is the main function to use for parsing CS2 logs with custom events

func ParseExtendedOnly

func ParseExtendedOnly(line string) (Message, error)

ParseExtendedOnly parses using only the extended patterns Useful for testing or when you only want custom events

func ParseLines

func ParseLines(lines []string) ([]Message, []error)

ParseLines takes multiple log lines and returns all parsed events This handles both single-line events and multi-line JSON blocks correctly

func ParseLinesEnhanced

func ParseLinesEnhanced(lines []string) ([]Message, []error)

ParseLinesEnhanced takes multiple log lines and uses ParseEnhanced for single-line events This provides access to all custom event types

func ParseLinesOrdered

func ParseLinesOrdered(lines []string) ([]Message, []error)

ParseLinesOrdered takes multiple log lines and uses ParseOrdered for single-line events This provides enhanced parsing with correct pattern priority

func ParseOrdered

func ParseOrdered(line string) (Message, error)

ParseOrdered parses using ordered patterns for correct priority

func ParseStateful

func ParseStateful(line string, state *ParserState) (Message, error)

ParseStateful parses a log line with state management for multi-line events Returns nil, nil if the line is part of an incomplete multi-line event Returns the complete Message when a multi-line event is completed

func ParseWithPatterns

func ParseWithPatterns(line string, patterns map[*regexp.Regexp]MessageFunc) (Message, error)

Parse attempts to match a plain log message against the map of provided patterns, if the line matches a key from the map, the corresponding MessageFunc is called on the line to parse it into a Message

type MessageFunc

type MessageFunc func(ti time.Time, r []string) Message

type Meta

type Meta struct {
	Time time.Time `json:"time"`
	Type string    `json:"type"`
}

Meta holds time and type of a log message

func NewMeta

func NewMeta(ti time.Time, ty string) Meta

func (Meta) GetTime

func (m Meta) GetTime() time.Time

GetTime is the getter for Meta.Time

func (Meta) GetType

func (m Meta) GetType() string

GetType is the getter fo Meta.Type

type OrderedPattern

type OrderedPattern struct {
	Pattern *regexp.Regexp
	Handler MessageFunc
}

OrderedPattern represents a pattern with its handler function

func GetOrderedPatterns

func GetOrderedPatterns() []OrderedPattern

GetOrderedPatterns returns all patterns in the correct priority order More specific patterns come before general patterns

type ParserState

type ParserState struct {
	InJSONBlock   bool
	JSONBuffer    []string
	JSONStartTime time.Time
	LastTimestamp string
}

ParserState maintains state for parsing multi-line events

func NewParserState

func NewParserState() *ParserState

NewParserState creates a new parser state

func (*ParserState) Reset

func (ps *ParserState) Reset()

Reset clears the parser state

type Player

type Player struct {
	Name    string `json:"name"`
	ID      int    `json:"id"`
	SteamID string `json:"steam_id"`
	Side    string `json:"side"`
}

Player holds the information about a player known from log

func NewPlayer

func NewPlayer(name, id, steamID, side string) Player

Helper function to create a Player struct

type PlayerAccolade

type PlayerAccolade struct {
	Meta
	Type    string  `json:"type"` // "3k", "4k", "5k", "mvp", etc.
	Player  Player  `json:"player"`
	Value   float64 `json:"value"`
	IsFinal bool    `json:"is_final"` // FINAL vs ROUND
}

PlayerAccolade is received when a player gets an achievement/award

type PlayerAttack

type PlayerAttack struct {
	Meta
	Attacker         Player   `json:"attacker"`
	AttackerPosition Position `json:"attacker_pos"`
	Victim           Player   `json:"victim"`
	VictimPosition   Position `json:"victim_pos"`
	Weapon           string   `json:"weapon"`
	Damage           int      `json:"damage"`
	DamageArmor      int      `json:"damage_armor"`
	Health           int      `json:"health"`
	Armor            int      `json:"armor"`
	Hitgroup         string   `json:"hitgroup"`
}

PlayerAttack is recieved when a player attacks another

type PlayerBanned

type PlayerBanned struct {
	Meta
	Player   Player `json:"player"`
	Duration string `json:"duration"`
	By       string `json:"by"`
}

PlayerBanned is received when a player gots banned from the server

type PlayerBlinded

type PlayerBlinded struct {
	Meta
	Attacker Player  `json:"attacker"`
	Victim   Player  `json:"victim"`
	For      float32 `json:"for"`
	Entindex int     `json:"entindex"`
}

PlayerBlinded is received when a player got blinded

type PlayerBombBeginDefuse

type PlayerBombBeginDefuse struct {
	Meta
	Player Player `json:"player"`
	Kit    bool   `json:"kit"`
}

PlayerBombBeginDefuse is received when a player begins defusing the bomb

type PlayerBombDefused

type PlayerBombDefused struct {
	Meta
	Player Player `json:"player"`
}

PlayerBombDefused is received when a player defused the bomb

type PlayerBombDropped

type PlayerBombDropped struct {
	Meta
	Player Player `json:"player"`
}

PlayerBombDropped is received when a player drops the bomb

type PlayerBombGot

type PlayerBombGot struct {
	Meta
	Player Player `json:"player"`
}

PlayerBombGot is received when a player picks up the bomb

type PlayerBombPlanted

type PlayerBombPlanted struct {
	Meta
	Player Player `json:"player"`
}

PlayerBombPlanted is received when a player plants the bomb

type PlayerConnected

type PlayerConnected struct {
	Meta
	Player  Player `json:"player"`
	Address string `json:"address"`
}

PlayerConnected message is received when a player connects and holds the address from where the player is connecting

type PlayerDisconnected

type PlayerDisconnected struct {
	Meta
	Player Player `json:"player"`
	Reason string `json:"reason"`
}

PlayerDisconnected is received when a player disconnets and holds the reason why the player left

type PlayerDropped

type PlayerDropped struct {
	Meta
	Player Player `json:"player"`
	Item   string `json:"item"`
}

PlayerDropped is recieved when a player drops an item

type PlayerEntered

type PlayerEntered struct {
	Meta
	Player Player `json:"player"`
}

PlayerEntered is received when a player enters the game

type PlayerFlashAssist

type PlayerFlashAssist struct {
	Meta
	Attacker Player `json:"attacker"`
	Victim   Player `json:"victim"`
}

PlayerFlashAssist is received when a player flash-assisted killing another

type PlayerKill

type PlayerKill struct {
	Meta
	Attacker         Player   `json:"attacker"`
	AttackerPosition Position `json:"attacker_pos"`
	Victim           Player   `json:"victim"`
	VictimPosition   Position `json:"victim_pos"`
	Weapon           string   `json:"weapon"`
	Headshot         bool     `json:"headshot"`
	Penetrated       bool     `json:"penetrated"`
}

PlayerKill is received when a player kills another

type PlayerKillAssist

type PlayerKillAssist struct {
	Meta
	Attacker Player `json:"attacker"`
	Victim   Player `json:"victim"`
}

PlayerKillAssist is received when a player assisted killing another

type PlayerKilledBomb

type PlayerKilledBomb struct {
	Meta
	Player   Player   `json:"player"`
	Position Position `json:"pos"`
}

PlayerKilledBomb is received when a player is killed by the bomb

type PlayerKilledSuicide

type PlayerKilledSuicide struct {
	Meta
	Player   Player   `json:"player"`
	Position Position `json:"pos"`
	With     string   `json:"with"`
}

PlayerKilledSuicide is received when a player commited suicide

type PlayerLeftBuyzone

type PlayerLeftBuyzone struct {
	Meta
	Player    Player   `json:"player"`
	Equipment []string `json:"equipment"`
}

PlayerLeftBuyzone is received when a player leaves the buy zone

type PlayerMoneyChange

type PlayerMoneyChange struct {
	Meta
	Player   Player   `json:"player"`
	Equation Equation `json:"equation"`
	Purchase string   `json:"purchase"`
}

PlayerMoneyChange is received when a player loses or receives money TODO: add before +-money

type PlayerPickedUp

type PlayerPickedUp struct {
	Meta
	Player Player `json:"player"`
	Item   string `json:"item"`
}

PlayerPickedUp is received when a player picks up an item

type PlayerPurchase

type PlayerPurchase struct {
	Meta
	Player Player `json:"player"`
	Item   string `json:"item"`
}

PlayerPurchase holds info about which player bought an item

type PlayerSay

type PlayerSay struct {
	Meta
	Player Player `json:"player"`
	Text   string `json:"text"`
	Team   bool   `json:"team"`
}

PlayerSay is received when a player writes into chat

type PlayerStatistics

type PlayerStatistics struct {
	AccountID      int     `json:"accountid"`
	Team           int     `json:"team"` // 1=T, 2=CT, 3=Spectator
	Money          int     `json:"money"`
	Kills          int     `json:"kills"`
	Deaths         int     `json:"deaths"`
	Assists        int     `json:"assists"`
	Damage         int     `json:"damage"`
	HeadshotPct    float64 `json:"headshot_pct"` // HSP percentage
	KDR            float64 `json:"kdr"`          // Kill/Death ratio
	ADR            int     `json:"adr"`          // Average Damage per Round
	MVP            int     `json:"mvp"`
	EnemiesFlashed int     `json:"enemies_flashed"` // EF
	UtilityDamage  int     `json:"utility_damage"`  // UD
	TripleKills    int     `json:"triple_kills"`    // 3K
	QuadKills      int     `json:"quad_kills"`      // 4K
	AceKills       int     `json:"ace_kills"`       // 5K
	ClutchKills    int     `json:"clutch_kills"`
	FirstKills     int     `json:"first_kills"`
	PistolKills    int     `json:"pistol_kills"`
	SniperKills    int     `json:"sniper_kills"`
	BlindKills     int     `json:"blind_kills"`
	BombKills      int     `json:"bomb_kills"`
	FireDamage     int     `json:"fire_damage"`
	UniqueKills    int     `json:"unique_kills"`
	Dinks          int     `json:"dinks"`
	ChickenKills   int     `json:"chicken_kills"`
}

PlayerStatistics represents detailed player statistics

type PlayerSwitched

type PlayerSwitched struct {
	Meta
	Player Player `json:"player"`
	From   string `json:"from"`
	To     string `json:"to"`
}

PlayerSwitched is received when a player switches sides

type PlayerThrew

type PlayerThrew struct {
	Meta
	Player   Player   `json:"player"`
	Position Position `json:"pos"`
	Entindex int      `json:"entindex"`
	Grenade  string   `json:"grenade"`
}

PlayerThrew is received when a player threw a grenade

type PlayerValidated

type PlayerValidated struct {
	Meta
	Player Player `json:"player"`
}

PlayerValidated is received when a player's Steam ID is validated

type Position

type Position struct {
	X int `json:"x"`
	Y int `json:"y"`
	Z int `json:"z"`
}

Position holds the coords for a event happend on the map

type PositionFloat

type PositionFloat struct {
	X float32 `json:"x"`
	Y float32 `json:"y"`
	Z float32 `json:"z"`
}

PositionFloat holds more exact coords

type ProjectileSpawned

type ProjectileSpawned struct {
	Meta
	Position PositionFloat `json:"pos"`
	Velocity Velocity      `json:"velocity"`
}

ProjectileSpawned is received when a molotov spawned

type RconCommand

type RconCommand struct {
	Meta
	Source  string `json:"source"`  // IP:Port of RCON client
	Command string `json:"command"` // Command executed
}

RconCommand is received when an RCON command is executed

type ServerCvar

type ServerCvar struct {
	Meta
	Name  string `json:"name"`
	Value string `json:"value"`
}

ServerCvar is received when a server variable changes

type ServerMessage

type ServerMessage struct {
	Meta
	Text string `json:"text"`
}

ServerMessage is received on a server event

type StartedMap

type StartedMap struct {
	Meta
	Map string `json:"map"`
}

StartedMap is received when map is fully loaded

type TeamNotice

type TeamNotice struct {
	Meta
	Side    string `json:"side"`
	Notice  string `json:"notice"`
	ScoreCT int    `json:"score_ct"`
	ScoreT  int    `json:"score_t"`
}

TeamNotice message is received at the end of a round and holds information about which team won the round and the score

type TeamPlaying

type TeamPlaying struct {
	Meta
	Side     string `json:"side"`      // "CT" or "TERRORIST"
	TeamName string `json:"team_name"` // Actual team name
}

TeamPlaying is received when team names are set

type TeamScored

type TeamScored struct {
	Meta
	Side       string `json:"side"`
	Score      int    `json:"score"`
	NumPlayers int    `json:"num_players"`
}

TeamScored is received at the end of each round and holds the scores for a team

type TriggeredEvent

type TriggeredEvent struct {
	Meta
	Event string            `json:"event"`
	Data  map[string]string `json:"data,omitempty"`
}

TriggeredEvent is a generic event for World triggered events

type Unknown

type Unknown struct {
	Meta
	Raw string `json:"raw"`
}

Unknown holds the raw log message of a message that is not defined in patterns but starts with time

type Velocity

type Velocity struct {
	X float32 `json:"x"`
	Y float32 `json:"y"`
	Z float32 `json:"z"`
}

Velocity holds information about the velocity of a projectile

type WarmupEnd

type WarmupEnd struct {
	Meta
}

WarmupEnd is received when warmup period ends

type WarmupStart

type WarmupStart struct {
	Meta
}

WarmupStart is received when warmup period starts

type WorldGameCommencing

type WorldGameCommencing struct{ Meta }

WorldGameCommencing message is received when a game is commencing

type WorldMatchStart

type WorldMatchStart struct {
	Meta
	Map string `json:"map"`
}

WorldMatchStart holds the map wich will be played when match starts

type WorldRoundEnd

type WorldRoundEnd struct{ Meta }

WorldRoundEnd message is received when a round ends

type WorldRoundRestart

type WorldRoundRestart struct {
	Meta
	Timeleft int `json:"timeleft"`
}

WorldRoundRestart is received when the server wants to restart a round

type WorldRoundStart

type WorldRoundStart struct{ Meta }

WorldRoundStart message is received when a new round starts

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL