Skip to content

Commit 8d22936

Browse files
committed
fix playerinfoblock parsing
1 parent 0f90ff8 commit 8d22936

File tree

5 files changed

+46
-34
lines changed

5 files changed

+46
-34
lines changed

.vscode/launch.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
{
88
"type": "lldb",
99
"request": "launch",
10-
"name": "Debug executable 'battlefield_rcon'",
10+
"name": "Debug executable 'battle_fox'",
1111
"cargo": {
1212
"args": [
1313
"build",
14-
"--bin=battlefield_rcon",
15-
"--package=battlefield_rcon"
14+
"--bin=battle_fox",
15+
"--package=battle_fox"
1616
],
1717
"filter": {
18-
"name": "battlefield_rcon",
18+
"name": "battle_fox",
1919
"kind": "bin"
2020
}
2121
},
@@ -25,16 +25,16 @@
2525
{
2626
"type": "lldb",
2727
"request": "launch",
28-
"name": "Debug unit tests in executable 'battlefield_rcon'",
28+
"name": "Debug unit tests in executable 'battle_fox'",
2929
"cargo": {
3030
"args": [
3131
"test",
3232
"--no-run",
33-
"--bin=battlefield_rcon",
34-
"--package=battlefield_rcon"
33+
"--bin=battle_fox",
34+
"--package=battle_fox"
3535
],
3636
"filter": {
37-
"name": "battlefield_rcon",
37+
"name": "battle_fox",
3838
"kind": "bin"
3939
}
4040
},

battlefield_rcon/src/bf4.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,22 @@ impl Bf4Client {
166166
} else {
167167
// welp, gotta ask rcon and update cache...
168168
// println!("[Bf4Client::resolve_player] Cache miss for {}, resolving...", name);
169-
let pib = match self.list_players(Visibility::Player(name.clone())).await { // hm, sucks that you need clone for this :/
170-
Ok(pib) => Ok(pib),
171-
Err(ListPlayersError::Rcon(RconError::InvalidArguments)) => {
172-
Err(Bf4Error::Rcon(RconError::other(format!("Failed to resolve player {}", name))))
169+
170+
// let pib = match self.list_players(Visibility::Player(name.clone())).await { // hm, sucks that you need clone for this :/
171+
// let pib = match self.list_players(Visibility::Squad(Team::One, Squad::Alpha)).await { // hm, sucks that you need clone for this :/
172+
let pib = match self.list_players(Visibility::All).await { // hm, sucks that you need clone for this :/
173+
Ok(pib) => pib,
174+
Err(ListPlayersError::Rcon(rcon)) => {
175+
return Err(Bf4Error::PlayerGuidResolveFailed { player_name: name.clone(), rcon: Some(rcon) } );
173176
},
174-
Err(ListPlayersError::Rcon(rcon)) => Err(rcon.into()),
175-
}?;
177+
};
176178
if pib.len() != 1 {
177179
// we expect exactly one
178-
return Err(Bf4Error::PlayerGuidResolveFailed);
180+
return Err(Bf4Error::PlayerGuidResolveFailed { player_name: name.clone(), rcon: None } );
179181
}
180182
if &pib[0].player_name != name {
181183
// wrong player returned? Wtf xD.
182-
return Err(Bf4Error::PlayerGuidResolveFailed);
184+
return Err(Bf4Error::PlayerGuidResolveFailed { player_name: name.clone(), rcon: None } );
183185
}
184186

185187
let player = Player {
@@ -319,7 +321,7 @@ impl Bf4Client {
319321

320322
pub async fn list_players(&self, vis: Visibility) -> Result<Vec<PlayerInfo>, ListPlayersError> {
321323
self.rcon.command(&veca!["admin.listPlayers", vis.to_rcon_format()],
322-
|ok| player_info_block::parse_pib(ok).map_err(|rconerr| rconerr.into()),
324+
|ok| player_info_block::parse_pib(&ok[1..]).map_err(|rconerr| rconerr.into()),
323325
err_none
324326
).await
325327
}

battlefield_rcon/src/bf4/ea_guid.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ impl Eaid {
2121
let guid_only = &ascii.as_slice()[3..]; // skip "EA_"
2222
Ok(Eaid(guid_only.try_into().unwrap())) // we can use unwrap here because we tested the length
2323
}
24+
} else if str.len() == 0 {
25+
Ok(Eaid([AsciiChar::X; 32]))
2426
} else {
2527
Err(EaidParseError)
2628
}

battlefield_rcon/src/bf4/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use ascii::AsciiString;
2+
13
use crate::rcon::RconError;
24

35
#[derive(Debug, Clone)]
46
pub enum Bf4Error {
5-
PlayerGuidResolveFailed,
7+
PlayerGuidResolveFailed{ player_name: AsciiString, rcon: Option<RconError> },
68
UnknownEvent(String),
79
Rcon(RconError),
810
Other(String),

battlefield_rcon/src/bf4/player_info_block.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ pub struct PlayerInfo {
2121
pub eaid: Eaid,
2222
pub squad: Squad,
2323
pub team: Team,
24-
pub kills: usize,
25-
pub deahts: usize,
26-
pub score: usize,
27-
pub rank: usize,
28-
pub ping: usize,
24+
pub kills: i32,
25+
pub deahts: i32,
26+
pub score: i32,
27+
pub rank: i32,
28+
pub ping: i32,
2929
}
3030

31-
fn parse_int(word: &AsciiString) -> RconResult<usize> {
32-
word.as_str().parse::<usize>().map_err(|_| RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: \"{}\" is not an unsigned integer", word)))
31+
fn parse_int(word: &AsciiString) -> RconResult<i32> {
32+
word.as_str().parse::<i32>().map_err(|_| RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: \"{}\" is not an unsigned integer", word)))
3333
}
3434

3535
// fn assert_len(words: &[AsciiString], len: usize) -> Bf4Result<()> {
@@ -49,27 +49,28 @@ pub fn parse_pib(words: &[AsciiString]) -> RconResult<Vec<PlayerInfo>> {
4949
// word offset.
5050
let mut offset = 0;
5151

52-
let n_columns = parse_int(&words[offset])?;
53-
if words.len() - offset < n_columns || n_columns != 9 { // currently there are 9 columns
54-
return Err(RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: Expected 9 columns")));
52+
const N_COLS : usize = 10;
53+
let n_columns = parse_int(&words[offset])? as usize;
54+
if words.len() - offset < n_columns || n_columns != N_COLS { // currently there are 9 columns
55+
return Err(RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: Expected {} columns", N_COLS)));
5556
}
5657
offset += 1;
5758

5859
// now read in the column names, make sure we're still talking about the same thing
59-
const COLS : [&'static str; 9] = ["name", "guid", "teamId", "squadId", "kills", "deaths", "score", "rank", "ping"];
60-
for i in 0..9 {
60+
const COLS : [&'static str; N_COLS] = ["name", "guid", "teamId", "squadId", "kills", "deaths", "score", "rank", "ping", "type"];
61+
for i in 0..N_COLS {
6162
let col_name = words[offset + i].as_str();
6263
if col_name != COLS[i] {
6364
return Err(RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: Column mismatch, did the rcon protocol change?")));
6465
}
6566
}
66-
offset += 9;
67+
offset += N_COLS;
6768

6869
// now read in how many rows (= players) we have.
6970
if words.len() - offset == 0 {
7071
return Err(RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock")));
7172
}
72-
let m_rows = parse_int(&words[offset])?;
73+
let m_rows = parse_int(&words[offset])? as usize;
7374
offset += 1;
7475

7576
// make sure there actually is enough words to read in, that that packet isn't malformed.
@@ -80,9 +81,14 @@ pub fn parse_pib(words: &[AsciiString]) -> RconResult<Vec<PlayerInfo>> {
8081
// now we actually read in the data.
8182
let mut pib = Vec::new();
8283
for _ in 0..m_rows {
84+
// let guid = if words[offset + 1].len() == 0 {
85+
// None
86+
// } else {
87+
// Some(Eaid::from_rcon_format(&words[offset + 1]).map_err(|_:EaidParseError| RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: Invalid EA GUID: {}", words[offset + 1])))?)
88+
// }
8389
let pi = PlayerInfo {
8490
player_name: words[offset + 0].clone(),
85-
eaid: Eaid::from_rcon_format(&words[offset + 1]).map_err(|_:EaidParseError| RconError::protocol_msg("Failed to parse PlayerInfoBlock: Invalid EA GUID"))?,
91+
eaid: Eaid::from_rcon_format(&words[offset + 1]).map_err(|_:EaidParseError| RconError::protocol_msg(format!("Failed to parse PlayerInfoBlock: Invalid EA GUID: {}", words[offset + 1])))?,
8692
team: Team::from_rcon_format(&words[offset + 2])?,
8793
squad: Squad::from_rcon_format(&words[offset + 3])?,
8894
kills: parse_int(&words[offset + 4])?,
@@ -94,7 +100,7 @@ pub fn parse_pib(words: &[AsciiString]) -> RconResult<Vec<PlayerInfo>> {
94100

95101
pib.push(pi);
96102

97-
offset += 9;
103+
offset += N_COLS;
98104
}
99105

100106
Ok(pib)

0 commit comments

Comments
 (0)