Skip to content

Commit

Permalink
Update entity parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
vikpe committed Jun 25, 2024
1 parent d358417 commit 5af3b68
Show file tree
Hide file tree
Showing 2 changed files with 494 additions and 105 deletions.
122 changes: 79 additions & 43 deletions src/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,38 @@ fn get_entities_maps(data: &[u8]) -> Result<Vec<HashMap<String, String>>> {
}

fn get_entities_string(data: &[u8]) -> Result<String> {
let needle_from: &[u8] = &[123, 10, 34];
let Some(index_from) = data.find(needle_from) else {
return Err(e!("Entities not found (start needle)"));
let Some(index_worldspawn) = data.find(br#""worldspawn""#) else {
return Err(e!("Entities not found (missing worldspawn)"));
};

let needle_to = &[10, 125, 10, 0];
let Some(index_to) = data[index_from..]
.find(needle_to)
.map(|i| index_from + i + 2)
else {
return Err(e!("Entities not found (end needle)"));
let Some(index_from) = data[..index_worldspawn].rfind(br#"{"#) else {
return Err(e!("Entities not found (first opening brace)"));
};

Ok(data[index_from..index_to].to_str()?.to_string())
let Some(index_nullterm) = data[index_from..].find_byte(0).map(|i| index_from + i) else {
return Err(e!("Entities not found (null terminator)"));
};

let Some(index_to) = data[..index_nullterm].rfind(b"}") else {
return Err(e!("Entities not found (last closing brace)"));
};

let plain_data: Vec<u8> = data[index_from..=index_to]
.iter()
.map(|b| *b & 127) // strip color
.collect();

let Ok(ent_str) = plain_data.to_str() else {
println!(
"range: {}-{} ({})",
index_from,
index_to,
index_to - index_from
);
return Err(e!("Entities not found (invalid UTF-8)"));
};

Ok(ent_str.to_string())
}

#[cfg(test)]
Expand All @@ -67,37 +85,55 @@ mod tests {

#[test]
fn test_get_entities() -> Result<()> {
let demo_data = fs::read("tests/files/dm3_gpl.bsp")?;
let entities = get_entities(&demo_data)?;

assert_eq!(entities.len(), 211);

let unknowns = entities
.iter()
.filter(|e| match e {
Entity::Unknown { .. } => true,
_ => false,
})
.count();
assert_eq!(unknowns, 0);

assert_eq!(
entities[0],
Entity::WorldSpawn {
message: "The Abandoned Base".to_string(),
sounds: "6".to_string(),
wad: "gfx/base.wad".to_string(),
worldtype: "2".to_string(),
}
);
{
let demo_data = fs::read("tests/files/dm3_gpl.bsp")?;
let entities = get_entities(&demo_data)?;

assert_eq!(
entities[210],
Entity::InfoIntermission {
mangle: "20 240 0".to_string(),
origin: "1840 256 64".to_string(),
}
);
assert_eq!(entities.len(), 211);

let unknowns = entities
.iter()
.filter(|e| match e {
Entity::Unknown { .. } => true,
_ => false,
})
.count();
assert_eq!(unknowns, 0);

assert_eq!(
entities[0],
Entity::WorldSpawn {
message: "The Abandoned Base".to_string(),
sounds: "6".to_string(),
wad: "gfx/base.wad".to_string(),
worldtype: "2".to_string(),
}
);

assert_eq!(
entities[210],
Entity::InfoIntermission {
mangle: "20 240 0".to_string(),
origin: "1840 256 64".to_string(),
}
);
}

{
let demo_data = fs::read("tests/files/povdmm4.bsp")?;
let entities = get_entities(&demo_data)?;

assert_eq!(entities.len(), 26);

let unknowns = entities
.iter()
.filter(|e| match e {
Entity::Unknown { .. } => true,
_ => false,
})
.count();
assert_eq!(unknowns, 0);
}

Ok(())
}
Expand All @@ -111,11 +147,11 @@ mod tests {
assert_eq!(
entities.get(0),
Some(&HashMap::from([
("wad".to_string(), "gfx/base.wad".to_string()),
("classname".to_string(), "worldspawn".to_string()),
("worldtype".to_string(), "2".to_string()),
("sounds".to_string(), "6".to_string()),
("message".to_string(), "The Abandoned Base".to_string()),
("sounds".to_string(), "6".to_string()),
("wad".to_string(), "gfx/base.wad".to_string()),
("worldtype".to_string(), "2".to_string()),
]))
);
assert_eq!(
Expand Down
Loading

0 comments on commit 5af3b68

Please sign in to comment.