{"id":32492880,"url":"https://github.com/kanghyojun/sc2ts","last_synced_at":"2025-10-27T11:56:13.830Z","repository":{"id":315098401,"uuid":"1058100992","full_name":"kanghyojun/sc2ts","owner":"kanghyojun","description":"SC2 replay parser for TypeScript","archived":false,"fork":false,"pushed_at":"2025-10-22T06:40:50.000Z","size":1035,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-22T08:33:52.621Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kanghyojun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-16T16:11:59.000Z","updated_at":"2025-10-22T06:40:54.000Z","dependencies_parsed_at":"2025-09-16T19:02:00.996Z","dependency_job_id":"5f9577e4-dc09-44ad-b15c-de4d2035f35e","html_url":"https://github.com/kanghyojun/sc2ts","commit_stats":null,"previous_names":["kanghyojun/sc2ts"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/kanghyojun/sc2ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanghyojun%2Fsc2ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanghyojun%2Fsc2ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanghyojun%2Fsc2ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanghyojun%2Fsc2ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kanghyojun","download_url":"https://codeload.github.com/kanghyojun/sc2ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanghyojun%2Fsc2ts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280878344,"owners_count":26406641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-24T02:00:06.418Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-27T11:56:10.558Z","updated_at":"2025-10-27T11:56:13.821Z","avatar_url":"https://github.com/kanghyojun.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sc2ts\n\nA comprehensive TypeScript library for parsing MPQ (MoPaQ) archive files and StarCraft II replay files. This library provides a modern, type-safe interface for reading Blizzard Entertainment's proprietary archive format.\n\n## Features\n\n- 🏗️ **MPQ Archive Support**: Read and extract files from MPQ archives\n- 🎮 **StarCraft II Replay Parsing**: Complete SC2 replay file analysis\n- 🖥️ **Command Line Interface**: Extract and analyze replays without coding\n- 📦 **Dual Module Support**: Both CommonJS and ESM exports\n- 🛡️ **Type Safety**: Full TypeScript support with comprehensive type definitions\n- 🧪 **Well Tested**: Extensive test coverage with real replay files\n- 🔍 **Binary Data Handling**: Advanced bit-packed data decoding\n- 📝 **Structured Logging**: Optional LogTape integration for debugging and monitoring\n- ⚡ **Modern Bundler Support**: Works seamlessly with Next.js, Webpack, Vite, and other modern bundlers\n\n## Installation\n\n```bash\nnpm install sc2ts\n# or\npnpm add sc2ts\n# or\nyarn add sc2ts\n```\n\n## Command Line Interface (CLI)\n\nsc2ts includes a powerful CLI tool for extracting and analyzing SC2 replay files without writing any code.\n\n### CLI Installation\n\nAfter installing the package, the `sc2ts` command becomes available:\n\n```bash\n# Install globally for CLI access\nnpm install -g sc2ts\n\n# Or use directly with npx\nnpx sc2ts --help\n```\n\n### CLI Commands\n\n#### Extract Files from Replays\n\nExtract files from SC2 replay archives in JSON or raw binary format:\n\n```bash\n# Extract all files as JSON (default)\nsc2ts extract replay.SC2Replay\n\n# Extract to specific directory\nsc2ts extract replay.SC2Replay --output ./extracted\n\n# Extract specific files only\nsc2ts extract replay.SC2Replay --files \"replay.details,replay.game.events\"\n\n# Extract as raw binary files\nsc2ts extract replay.SC2Replay --format raw\n\n# Pretty print JSON output\nsc2ts extract replay.SC2Replay --pretty\n\n# Verbose output\nsc2ts extract replay.SC2Replay --verbose\n```\n\n**Extract Command Options:**\n- `--output, -o \u003cdir\u003e`: Output directory (default: `./extracted`)\n- `--format, -f \u003cformat\u003e`: Output format - `json` or `raw` (default: `json`)\n- `--files \u003cfiles\u003e`: Comma-separated list of files to extract (default: `all`)\n- `--pretty`: Pretty print JSON output\n- `--verbose, -v`: Show detailed extraction progress\n\n#### List Files in Archive\n\nDisplay all files available in an SC2 replay archive:\n\n```bash\n# Simple file listing\nsc2ts list replay.SC2Replay\n\n# Show detailed file information\nsc2ts list replay.SC2Replay --details\n\n# Filter files by name\nsc2ts list replay.SC2Replay --filter \"events\"\n\n# Verbose output\nsc2ts list replay.SC2Replay --verbose\n```\n\n**List Command Options:**\n- `--details, -d`: Show detailed file information (size, compression, etc.)\n- `--filter, -f \u003cpattern\u003e`: Filter files by name pattern\n- `--verbose, -v`: Show additional information\n\n#### Display Replay Information\n\nShow comprehensive information about SC2 replay files:\n\n```bash\n# Basic replay information\nsc2ts info replay.SC2Replay\n\n# Show detailed player information\nsc2ts info replay.SC2Replay --players\n\n# Show event statistics\nsc2ts info replay.SC2Replay --events\n\n# Output as JSON\nsc2ts info replay.SC2Replay --json\n\n# All options combined\nsc2ts info replay.SC2Replay --players --events --json --verbose\n```\n\n**Info Command Options:**\n- `--json, -j`: Output information as JSON\n- `--players, -p`: Show detailed player information\n- `--events, -e`: Show event counts and statistics\n- `--verbose, -v`: Show additional technical details\n\n#### Parse Replay Data (Human-Readable)\n\nParse and display SC2 replay data in a human-readable format:\n\n```bash\n# Parse replay with human-readable output\nsc2ts parse replay.SC2Replay\n\n# Parse with verbose information\nsc2ts parse replay.SC2Replay --verbose\n\n# Parse and save as JSON\nsc2ts parse replay.SC2Replay --json --pretty --output parsed_replay.json\n\n# Parse and output JSON to console\nsc2ts parse replay.SC2Replay --json --pretty\n```\n\n**Parse Command Options:**\n- `--output, -o \u003cfile\u003e`: Save parsed data to file (JSON format only)\n- `--json, -j`: Output as structured JSON instead of human-readable format\n- `--pretty`: Pretty-print JSON output (only works with --json)\n- `--verbose, -v`: Show verbose parsing information\n\n**Parse vs Extract vs Info:**\n- `extract`: Extracts raw binary files from replay archive (base64 encoded)\n- `info`: Shows basic replay metadata and statistics\n- `parse`: **NEW!** Parses replay data into human-readable format with game details, players, chat messages, and event summaries\n\n### CLI Examples\n\n#### Complete Workflow Example\n\n```bash\n# 1. First, examine the replay file\nsc2ts info replay.SC2Replay --players\n# Output: Shows game info, players, duration, etc.\n\n# 2. See what files are available\nsc2ts list replay.SC2Replay --details\n# Output: Lists all extractable files with sizes\n\n# 3. Extract specific game data\nsc2ts extract replay.SC2Replay --files \"replay.details,replay.game.events\" --pretty\n\n# 4. Extract all files as raw binaries for advanced analysis\nsc2ts extract replay.SC2Replay --format raw --output ./raw_data\n```\n\n#### Batch Processing\n\n```bash\n# Process multiple replays (using shell scripting)\nfor replay in *.SC2Replay; do\n  echo \"Processing $replay...\"\n  sc2ts info \"$replay\" --json \u003e \"${replay%.SC2Replay}_info.json\"\n  sc2ts extract \"$replay\" --files \"replay.details\" --output \"./details/\"\ndone\n```\n\n### Supported Files for Extraction\n\nThe CLI can extract these files from SC2 replay archives:\n\n- **`(attributes)`** - Game attributes and settings\n- **`(listfile)`** - Archive file listing\n- **`replay.attributes.events`** - Game attribute events\n- **`replay.details`** - Game details and player information\n- **`replay.game.events`** - All gameplay events and actions\n- **`replay.initData`** - Game initialization data\n- **`replay.load.info`** - Loading screen information\n- **`replay.message.events`** - Chat messages and pings\n- **`replay.server.battlelobby`** - Battle.net lobby information\n- **`replay.sync.events`** - Synchronization events\n- **`replay.tracker.events`** - Detailed unit/building tracking\n\n### Output Formats\n\n#### JSON Format\n\nWhen using `--format json` (default), files are extracted as structured JSON with metadata:\n\n```json\n{\n  \"filename\": \"replay.details\",\n  \"fileSize\": 2048,\n  \"compressedSize\": 1024,\n  \"flags\": 2,\n  \"data\": \"base64-encoded-content...\",\n  \"metadata\": {\n    \"isCompressed\": true,\n    \"compressionRatio\": 0.5\n  }\n}\n```\n\n#### Raw Format\n\nWhen using `--format raw`, files are extracted as their original binary data, perfect for advanced analysis or processing with other tools.\n\n## Quick Start\n\n### Basic MPQ Archive Usage\n\n```typescript\nimport { MpqArchive } from 'sc2ts';\nimport { readFileSync } from 'fs';\n\n// Method 1: Load from buffer (async)\nconst buffer = readFileSync('example.mpq');\nconst archive = await MpqArchive.fromBuffer(buffer);\n\n// Method 2: Load from file path (async)\nconst archive2 = await MpqArchive.open('example.mpq');\n\n// List all files in the archive\nconst files = archive.listFiles();\nconsole.log('Files in archive:', files);\n\n// Extract a specific file (async)\nconst fileData = await archive.getFile('path/to/file.txt');\nconsole.log('File content:', fileData.data.toString());\nconsole.log('Original size:', fileData.fileSize);\nconsole.log('Compressed size:', fileData.compressedSize);\n\n// Check if file exists\nif (archive.hasFile('some/file.dat')) {\n  console.log('File exists!');\n}\n\n// Get archive information\nconsole.log('Archive has', archive.fileCount, 'files');\n```\n\n### StarCraft II Replay Analysis\n\n```typescript\nimport { SC2Replay } from 'sc2ts';\nimport { readFileSync } from 'fs';\n\n// Method 1: Load from buffer (async)\nconst replayBuffer = readFileSync('replay.SC2Replay');\nconst replay = await SC2Replay.fromBuffer(replayBuffer);\n\n// Method 2: Load from file path (async)\nconst replay2 = await SC2Replay.fromFile('replay.SC2Replay');\n\n// Get basic replay information\nconsole.log('Map name:', replay.replayDetails?.title);\nconsole.log('Game duration:', replay.duration, 'seconds');  // Getter property\nconsole.log('Game loops:', replay.gameLength);              // Getter property\nconsole.log('Players:', replay.players.length);\n\n// Access player information\nreplay.players.forEach((player, index) =\u003e {\n  console.log(`Player ${index + 1}:`, {\n    name: player.name,\n    race: player.race,\n    teamId: player.teamId,\n    color: player.color,\n    result: player.result  // 1 = Win, 2 = Loss, 3 = Tie\n  });\n});\n\n// Get the winner (getter property)\nconst winner = replay.winner;\nif (winner) {\n  console.log('Winner:', winner.name);\n}\n\n// Access replay events\nconsole.log('Game events:', replay.gameEvents.length);\nconsole.log('Chat messages:', replay.messageEvents.length);\nconsole.log('Tracker events:', replay.trackerEvents.length);\n```\n\n### Advanced Replay Parsing with Options\n\n```typescript\nimport { SC2Replay } from 'sc2ts';\n\nconst replay = await SC2Replay.fromBuffer(buffer, {\n  // Enable/disable specific event parsing for performance\n  decodeGameEvents: true,     // Parse gameplay events (default: true)\n  decodeMessageEvents: true,  // Parse chat messages (default: true)\n  decodeTrackerEvents: true,  // Parse detailed tracking events (default: true)\n  decodeInitData: false       // Parse initialization data (default: false)\n});\n\n// Access different types of events\nconsole.log('Game events:', replay.gameEvents.length);\nconsole.log('Message events:', replay.messageEvents.length);\nconsole.log('Tracker events:', replay.trackerEvents.length);\n\n// Example: Find all chat messages\nreplay.messageEvents.forEach(msg =\u003e {\n  if (msg._event === 'NNet.Game.SChatMessage') {\n    console.log(`Player ${msg.m_userId}: ${msg.m_string}`);\n  }\n});\n```\n\n### Low-Level MPQ Reader Usage\n\n```typescript\nimport { MpqReader } from 'sc2ts';\n\nconst reader = new MpqReader(buffer);\n\n// Read MPQ header information\nconst header = reader.readMpqHeader();\nconsole.log('MPQ Format Version:', header.formatVersion);\nconsole.log('Archive Size:', header.archiveSize);\n\n// Access hash and block tables\nconst hashTable = reader.readHashTable(header);\nconst blockTable = reader.readBlockTable(header);\n\nconsole.log('Hash entries:', hashTable.length);\nconsole.log('Block entries:', blockTable.length);\n```\n\n### Error Handling\n\n```typescript\nimport { MpqError, MpqInvalidFormatError, SC2Replay } from 'sc2ts';\n\ntry {\n  const replay = await SC2Replay.fromBuffer(buffer);\n  console.log('Replay parsed successfully');\n} catch (error) {\n  if (error instanceof MpqInvalidFormatError) {\n    console.error('Invalid MPQ format:', error.message);\n  } else if (error instanceof MpqError) {\n    console.error('MPQ parsing error:', error.message);\n  } else {\n    console.error('Unexpected error:', error);\n  }\n}\n```\n\n### Logging Configuration (Optional)\n\nsc2ts uses [LogTape](https://logtape.org/) for structured logging. Following LogTape's best practices for library authors, **sc2ts does not configure logging itself** - it's up to your application to configure logging if you want to see debug output.\n\n#### Basic Logging Setup\n\nIf you want to see debug logs from sc2ts in your application:\n\n```typescript\nimport { configure, getConsoleSink } from '@logtape/logtape';\nimport { SC2Replay } from 'sc2ts';\n\n// Configure LogTape in your application (not in the library)\nawait configure({\n  sinks: {\n    console: getConsoleSink(),\n  },\n  loggers: [\n    // Configure sc2ts logging\n    {\n      category: ['sc2ts'],\n      lowestLevel: 'debug',  // Show all debug logs\n      sinks: ['console'],\n    },\n  ],\n});\n\n// Now sc2ts will log debug information\nconst replay = await SC2Replay.fromFile('replay.SC2Replay');\n// Logs will show: MPQ header parsing, file extraction, decompression, etc.\n```\n\n#### Log Categories\n\nsc2ts uses these log categories (all under the `sc2ts` namespace):\n\n- `['sc2ts', 'mpq-archive']` - MPQ archive parsing and file extraction\n- `['sc2ts', 'mpq-reader']` - Low-level binary reading and decryption\n- `['sc2ts', 'sc2-replay']` - SC2 replay parsing\n- `['sc2ts', 'protocol']` - Protocol decoder and event parsing\n- `['sc2ts', 'cli']` - CLI command execution\n- `['sc2ts', 'cli-extractor']` - CLI file extraction\n- `['sc2ts', 'cli-formatter']` - CLI output formatting\n\n#### Production vs Development\n\n```typescript\nawait configure({\n  sinks: {\n    console: getConsoleSink(),\n  },\n  loggers: [\n    {\n      category: ['sc2ts'],\n      // Only show warnings and errors in production\n      lowestLevel: process.env.NODE_ENV === 'production' ? 'warning' : 'debug',\n      sinks: ['console'],\n    },\n  ],\n});\n```\n\n#### Disabling Logs\n\nIf you don't configure LogTape, sc2ts will not produce any log output. This is intentional - libraries should not force logging configuration on applications.\n\n#### Custom Logger Access\n\nIf you're building tools on top of sc2ts and want to use the same logger:\n\n```typescript\nimport { getScLogger } from 'sc2ts';\n\n// Create a logger for your module (will be under ['sc2ts', 'your-module'])\nconst logger = getScLogger('your-module');\n\nlogger.info('Processing replay batch', { count: 10 });\nlogger.debug('Detailed processing info', { fileSize: 1024 });\n```\n\nFor more information about LogTape configuration, see the [LogTape documentation](https://logtape.org/).\n\n## API Reference\n\n### MpqArchive\n\nThe main class for working with MPQ archives.\n\n#### Static Methods\n```typescript\nMpqArchive.fromBuffer(buffer: Buffer, options?: MpqParseOptions): Promise\u003cMpqArchive\u003e\nMpqArchive.open(filepath: string, options?: MpqParseOptions): Promise\u003cMpqArchive\u003e\n```\n\n#### Constructor (Advanced)\n```typescript\nnew MpqArchive(reader: MpqReader)\n```\n\n#### Properties (Getters)\n- `fileCount: number` - Number of files in the archive\n- `archiveHeader: MpqHeader | null` - MPQ archive header information\n\n#### Methods\n- `listFiles(): string[]` - Get list of all file paths\n- `getFile(filename: string): Promise\u003cMpqFile\u003e` - Extract file content and metadata (async)\n- `hasFile(filename: string): boolean` - Check if file exists\n- `getUserDataContent(): Buffer | null` - Get user data content from SC2 replays\n\n### SC2Replay\n\nParser for StarCraft II replay files.\n\n#### Static Methods\n```typescript\nSC2Replay.fromBuffer(buffer: Buffer, options?: ReplayOptions): Promise\u003cSC2Replay\u003e\nSC2Replay.fromFile(filepath: string, options?: ReplayOptions): Promise\u003cSC2Replay\u003e\n```\n\n#### Properties (Getters)\n- `replayHeader: ReplayHeader | null` - Replay file header\n- `replayDetails: ReplayDetails | null` - Game details and metadata\n- `replayInitData: ReplayInitData | null` - Initialization data (if parsed)\n- `players: Player[]` - Array of player information\n- `gameEvents: GameEvent[]` - Gameplay events\n- `messageEvents: MessageEvent[]` - Chat messages and pings\n- `trackerEvents: TrackerEvent[]` - Detailed unit/building tracking events\n- `gameLength: number` - Game length in game loops\n- `duration: number` - Game duration in seconds (gameLength / 16)\n- `winner: Player | null` - Winning player\n- `mpqArchive: MpqArchive` - Access to underlying MPQ archive\n\n### Types\n\nThe library exports comprehensive TypeScript types:\n\n```typescript\nimport type {\n  MpqHeader,\n  MpqHashTableEntry,\n  MpqBlockTableEntry,\n  MpqFile,\n  MpqParseOptions,\n  ReplayHeader,\n  ReplayDetails,\n  ReplayInitData,\n  ReplayData,\n  Player,\n  GameEvent,\n  MessageEvent,\n  TrackerEvent,\n  ReplayOptions\n} from 'sc2ts';\n```\n\n## Development\n\n### Setup\n\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd sc2ts\n\n# Install dependencies (this also sets up Git hooks via Husky)\npnpm install\n\n# Build the library\npnpm run build\n\n# Run tests\npnpm run test\n\n# Watch mode for development\npnpm run dev\n```\n\n**Note**: `pnpm install` automatically sets up Git hooks (via Husky) that run quality checks before each commit. This ensures code quality and prevents regressions.\n\n### Scripts\n\n- `pnpm run build` - Build both CommonJS and ESM versions + CLI\n- `pnpm run dev` - Watch mode for development\n- `pnpm run dev:cli` - Run CLI in development mode\n- `pnpm run test` - Run test suite\n- `pnpm run test:watch` - Run tests in watch mode\n- `pnpm run test:coverage` - Run tests with coverage report\n- `pnpm run lint` - Lint code\n- `pnpm run typecheck` - Type checking\n\n### Testing the CLI\n\nAfter building, you can test the CLI locally:\n\n```bash\n# Build the project\npnpm run build\n\n# Test CLI commands\n./bin/run.mjs --help\n./bin/run.mjs extract replay.SC2Replay\n./bin/run.mjs list replay.SC2Replay --details\n./bin/run.mjs info replay.SC2Replay --players\n```\n\n## File Format Support\n\n### MPQ Archives\n- MPQ format versions 0-4\n- Hash table and block table parsing\n- File compression support\n- Encrypted file detection\n\n### StarCraft II Replays\n- All modern SC2 replay versions\n- Header and metadata parsing\n- Player information extraction\n- Game events decoding\n- Chat message parsing\n- Tracker events (detailed statistics)\n\n## Performance Considerations\n\n- Use parsing options to disable unnecessary event decoding\n- The library handles large replay files efficiently\n- Memory usage scales with enabled parsing options\n- Consider streaming for very large archives\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n## License\n\nMIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\n- Based on analysis of Blizzard's [s2protocol](https://github.com/Blizzard/s2protocol) implementation\n- MPQ format documentation and community research\n- StarCraft II community for replay format insights\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanghyojun%2Fsc2ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkanghyojun%2Fsc2ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanghyojun%2Fsc2ts/lists"}