Skip to content

Commit

Permalink
Merge pull request #32 from ryantaylor/items-fix
Browse files Browse the repository at this point in the history
Fix Inconsistent Item Parsing
  • Loading branch information
ryantaylor authored Sep 13, 2024
2 parents 5422f7e + fe38ee1 commit 14d450a
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 118 deletions.
35 changes: 10 additions & 25 deletions CoH3Rec.bt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ struct CHUNKHEADER {
};

struct ITEM {
uint32 count;
uint32 id_a;
if (id_a == 0) {
uint32 sublength_maybe;
Expand All @@ -73,29 +72,9 @@ struct ITEM {
uint64 some_crazy_number;
uint64 itemlocation_id;
char rest_data[length - (FTell() - start)];
uint32 spacer;
};

uint32 GetItemCount(char faction[])
{
if (global_version < 10000) {
if (faction == "british_africa")
return 21;
else if (faction == "americans")
return 22;
else
return 25;
} else {
if (faction == "british_africa")
return 21;
else if (faction == "americans")
return 22;
else if (faction == "germans")
return 25;
else
return 28;
}
}

struct PLAYER {
ubyte is_human;
uint32 name_length;
Expand Down Expand Up @@ -124,9 +103,15 @@ struct PLAYER {
uint32 flag_b;
uint32 flag_c;
uint16 flag_d;
if (is_human == 1) ITEM items[GetItemCount(faction)] <optimize=false>;
else char data[44];
uint32 zero_six;
if (is_human == 1) {
uint32 battlegroup_count;
ITEM battlegroup_items[battlegroup_count] <optimize=false>;
uint32 spacer;
uint32 cosmetics_count;
ITEM cosmetic_items[cosmetics_count] <optimize=false>;
} else {
char data[48];
}
};

struct OPTIONCONFIG {
Expand Down
2 changes: 1 addition & 1 deletion src/data/chunks/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl Chunk {
return match &header.chunk_kind as &str {
"DATA" => match &header.chunk_type as &str {
"AUTO" => DataAutoChunk::parse(input, header),
"DATA" => DataDataChunk::parse(input, header, version),
"DATA" => DataDataChunk::parse(input, header),
"SDSC" => DataSdscChunk::parse(input, header),
_ => TrashDataChunk::parse(input, header),
},
Expand Down
8 changes: 4 additions & 4 deletions src/data/chunks/data_data_chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub struct DataDataChunk {

impl DataDataChunk {
#[tracable_parser]
pub fn parse(input: Span, header: Header, version: u16) -> ParserResult<Chunk> {
pub fn parse(input: Span, header: Header) -> ParserResult<Chunk> {
if header.version == 1 {
return TrashDataChunk::parse(input, header);
}
Expand All @@ -55,7 +55,7 @@ impl DataDataChunk {
tuple((
Self::parse_opponent_type,
take(6u32),
Self::parse_players(version),
Self::parse_players,
length_data(le_u32),
Self::parse_skirmish_flag,
le_u64,
Expand Down Expand Up @@ -96,8 +96,8 @@ impl DataDataChunk {
le_u32(input)
}

fn parse_players(version: u16) -> impl FnMut(Span) -> ParserResult<Vec<Player>> {
move |input: Span| length_count(le_u32, Player::parse_player(version))(input)
fn parse_players(input: Span) -> ParserResult<Vec<Player>> {
length_count(le_u32, Player::parse_player)(input)
}

#[tracable_parser]
Expand Down
40 changes: 5 additions & 35 deletions src/data/item.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,24 @@
use crate::data::{ParserResult, Span};
use nom::bytes::complete::take;
use nom::combinator::{cut, map, peek};
use nom::combinator::{cut, map};
use nom::multi::length_data;
use nom::number::complete::le_u32;
use nom::sequence::tuple;
use nom_tracable::tracable_parser;

#[derive(Debug)]
pub struct Item {
_data: Vec<u8>,
}

impl Item {
#[tracable_parser]
pub fn parse_item(input: Span) -> ParserResult<Item> {
cut(map(
tuple((
take(4u32),
Self::parse_sublength,
take(20u32),
length_data(le_u32),
)),
|(_, _, _, data)| Item {
tuple((take(24u32), length_data(le_u32), take(4u32))),
|(_, data, _): (Span, Span, Span)| Item {
_data: data.to_vec(),
},
))(input)
}

pub fn get_item_count(faction: &str, version: u16) -> usize {
if version < 10000 {
match faction {
"british_africa" => 21,
"americans" => 22,
_ => 25,
}
} else {
match faction {
"british_africa" => 21,
"americans" => 22,
"germans" => 25,
_ => 28,
}
}
}

fn parse_sublength(input: Span) -> ParserResult<Span> {
let (input, id) = peek(le_u32)(input)?;

if id == 0 {
take(12u32)(input)
} else {
take(4u32)(input)
}
}
}
106 changes: 53 additions & 53 deletions src/data/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::data::Item;
use crate::data::{ParserResult, Span};
use nom::bytes::complete::take;
use nom::combinator::{cut, map};
use nom::multi::many_m_n;
use nom::multi::length_count;
use nom::number::complete::{le_u32, le_u64, le_u8};
use nom::sequence::tuple;
use nom::IResult;
Expand All @@ -23,49 +23,46 @@ pub struct Player {
}

impl Player {
pub fn parse_player(version: u16) -> impl FnMut(Span) -> ParserResult<Player> {
move |input: Span| {
let (input, player) = cut(map(
tuple((
le_u8,
Self::parse_name,
Self::parse_team,
le_u32,
take(1u32),
Self::parse_faction,
take(8u32),
Self::parse_ai,
take(40u32),
le_u64,
take(1u32),
Self::parse_steam_id,
take(18u32),
)),
|(human, name, team, id, _, faction, _, ai_type, _, profile_id, _, steam_id, _)| {
Player {
id,
human,
name,
team,
faction,
_ai_type: ai_type,
steam_id,
profile_id,
_items: vec![],
}
},
))(input)?;

let (input, items) = Self::parse_items(input, &player, version)?;
let (input, _) = take(4u32)(input)?;
Ok((
input,
pub fn parse_player(input: Span) -> ParserResult<Player> {
let (input, player) = cut(map(
tuple((
le_u8,
Self::parse_name,
Self::parse_team,
le_u32,
take(1u32),
Self::parse_faction,
take(8u32),
Self::parse_ai,
take(40u32),
le_u64,
take(1u32),
Self::parse_steam_id,
take(18u32),
)),
|(human, name, team, id, _, faction, _, ai_type, _, profile_id, _, steam_id, _)| {
Player {
_items: items,
..player
},
))
}
id,
human,
name,
team,
faction,
_ai_type: ai_type,
steam_id,
profile_id,
_items: vec![],
}
},
))(input)?;

let (input, items) = Self::parse_items(input, &player)?;
Ok((
input,
Player {
_items: items,
..player
},
))
}

#[tracable_parser]
Expand Down Expand Up @@ -93,20 +90,23 @@ impl Player {
Ok((input, steam_id))
}

fn parse_items<'a>(
input: Span<'a>,
player: &Player,
version: u16,
) -> IResult<Span<'a>, Vec<Item>> {
#[tracable_parser]
fn parse_items<'a>(input: Span<'a>, player: &Player) -> IResult<Span<'a>, Vec<Item>> {
if player.human == 0 {
let (input, _) = take(44u32)(input)?;
let (input, _) = take(48u32)(input)?;
return Ok((input, vec![]));
}

cut(many_m_n(
0,
Item::get_item_count(&player.faction, version),
Item::parse_item,
cut(map(
tuple((
length_count(le_u32, Item::parse_item),
take(4u32),
length_count(le_u32, Item::parse_item),
)),
|(mut battlegroup_items, _, mut cosmetic_items)| {
battlegroup_items.append(&mut cosmetic_items);
battlegroup_items
},
))(input)
}
}

0 comments on commit 14d450a

Please sign in to comment.