| Crates.io | shk_parser |
| lib.rs | shk_parser |
| version | 0.1.1 |
| created_at | 2025-07-28 18:00:16.012333+00 |
| updated_at | 2025-07-28 21:18:05.09449+00 |
| description | A parser for Stronghold Kingdoms attack formation files (.cas) |
| homepage | |
| repository | https://github.com/yourusername/shk_parser |
| max_upload_size | |
| id | 1771438 |
| size | 51,798 |
A Rust library for parsing Stronghold Kingdoms attack formation files (.cas files).
Enable additional functionality with cargo features:
[dependencies]
shk_parser = { version = "0.1.0", features = [
"serde",
"tsify",
"cli"
] }
serde: Enables JSON serialization/deserializationtsify: Enables TypeScript type generation for WASM bindings (requires serde)cli: Enables the command-line interfaceAdd this to your Cargo.toml:
[dependencies]
shk_parser = "0.1.0"
Parse a formation file:
use shk_parser::parse_formation_file;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let units = parse_formation_file("my_formation.cas")?;
println!("Formation contains {} units:", units.len());
for (i, unit) in units.iter().enumerate() {
println!(" {}: {}", i + 1, unit);
}
Ok(())
}
The parser supports all Stronghold Kingdoms unit types:
// Parse from raw bytes
fn parse_formation(data: &[u8]) -> Result<Vec<UnitRecord>, ParseError>
// Parse directly from file path
fn parse_formation_file<P: AsRef<Path>>(path: P) -> Result<Vec<UnitRecord>, ParseError>
pub struct UnitRecord {
pub position: Position,
pub unit_type: UnitType,
}
pub struct Position {
pub x: u8,
pub y: u8,
}
pub enum UnitType {
Archer,
Pikeman,
Catapult { target: Position },
Captain { ability: CaptainAbility, wait_time: u8 },
Unknown(u8),
}
pub enum CaptainAbility {
Delay,
RallyingCry,
ArrowVolley { target: Position },
BattleCry,
CatapultsVolley { target: Position },
Unknown(u8),
}
With the cli feature enabled, you can use the binary tool:
# Parse all test files (default behavior)
cargo run --features cli --bin parse_formations
# Parse specific files
cargo run --features cli --bin parse_formations -- file1.cas file2.cas
# Verbose output with detailed parsing info
cargo run --features cli --bin parse_formations -- --verbose file.cas
# JSON output (requires serde feature)
cargo run --features cli,serde --bin parse_formations -- --format json file.cas
A parser for Stronghold Kingdoms formation files (.cas)
Usage: parse_formations [OPTIONS] [FILES]...
Arguments:
[FILES]... Formation file(s) to parse
Options:
-f, --format <FORMAT> Output format [default: human]
-v, --verbose Show detailed unit information
-h, --help Print help
.cas files use a simple binary format:
| Unit Type | Size | Format |
|---|---|---|
| Archer/Pikeman | 3 bytes | x, y, unit_type |
| Catapult | 5 bytes | x, y, unit_type, target_x, target_y |
| Captain (simple) | 4 bytes | x, y, unit_type, wait_time |
| Captain (with target) | 6 bytes | x, y, unit_type, wait_time, target_x, target_y |
use shk_parser::parse_formation_file;
let units = parse_formation_file("formation.cas")?;
for unit in &units {
match &unit.unit_type {
UnitType::Archer => println!("Archer at ({}, {})", unit.position.x, unit.position.y),
UnitType::Captain { ability, wait_time } => {
println!("Captain using {:?} for {}s at ({}, {})",
ability, wait_time, unit.position.x, unit.position.y);
}
_ => println!("{}", unit),
}
}
use shk_parser::{parse_formation_file, UnitType};
let units = parse_formation_file("formation.cas")?;
// Find all captains
let captains: Vec<_> = units.iter()
.filter(|unit| matches!(unit.unit_type, UnitType::Captain { .. }))
.collect();
println!("Found {} captains", captains.len());
use shk_parser::{parse_formation_file, UnitType, CaptainAbility};
let units = parse_formation_file("formation.cas")?;
for unit in &units {
if let UnitType::Captain { ability, wait_time } = &unit.unit_type {
match ability {
CaptainAbility::ArrowVolley { target } => {
println!("Arrow volley targeting ({}, {}) after {}s",
target.x, target.y, wait_time);
}
CaptainAbility::Delay => {
println!("Waiting for {}s", wait_time);
}
_ => println!("Captain ability: {:?}", ability),
}
}
}
The library provides detailed error information:
use shk_parser::{parse_formation_file, ParseError};
match parse_formation_file("formation.cas") {
Ok(units) => println!("Parsed {} units", units.len()),
Err(ParseError::FileNotFound(path)) => eprintln!("File not found: {}", path),
Err(ParseError::InvalidFormat(msg)) => eprintln!("Invalid file format: {}", msg),
Err(ParseError::IoError(err)) => eprintln!("IO error: {}", err),
}
Run the test suite:
cargo test
The library includes tests with real .cas files to ensure compatibility.
Licensed under either of
at your option.