log bad commands
This commit is contained in:
parent
ecd378f0d9
commit
36c16aa8c7
3 changed files with 52 additions and 46 deletions
|
@ -13,6 +13,12 @@ pub enum MatchLogMessage {
|
||||||
GameState(State),
|
GameState(State),
|
||||||
#[serde(rename = "stderr")]
|
#[serde(rename = "stderr")]
|
||||||
StdErr(StdErrMessage),
|
StdErr(StdErrMessage),
|
||||||
|
#[serde(rename = "bad_command")]
|
||||||
|
BadCommand {
|
||||||
|
player_id: u32,
|
||||||
|
command: String,
|
||||||
|
error: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::convert::TryInto;
|
||||||
|
|
||||||
pub use planetwars_rules::config::{Config, Map};
|
pub use planetwars_rules::config::{Config, Map};
|
||||||
|
|
||||||
use planetwars_rules::protocol::{self as proto, PlayerAction};
|
use planetwars_rules::protocol as proto;
|
||||||
use planetwars_rules::serializer as pw_serializer;
|
use planetwars_rules::serializer as pw_serializer;
|
||||||
use planetwars_rules::{PlanetWars, PwConfig};
|
use planetwars_rules::{PlanetWars, PwConfig};
|
||||||
|
|
||||||
|
@ -44,12 +44,8 @@ impl PwMatch {
|
||||||
let player_messages = self.prompt_players().await;
|
let player_messages = self.prompt_players().await;
|
||||||
|
|
||||||
for (player_id, turn) in player_messages {
|
for (player_id, turn) in player_messages {
|
||||||
let res = self.execute_action(player_id, turn);
|
let player_action = self.execute_action(player_id, turn);
|
||||||
if let Some(err) = action_errors(res) {
|
self.log_player_action(player_id, player_action);
|
||||||
let _info_str = serde_json::to_string(&err).unwrap();
|
|
||||||
// TODO
|
|
||||||
// println!("player {}: {}", player_id, info_str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.match_state.step();
|
self.match_state.step();
|
||||||
|
|
||||||
|
@ -88,18 +84,14 @@ impl PwMatch {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_action(
|
fn execute_action(&mut self, player_num: usize, turn: RequestResult<Vec<u8>>) -> PlayerAction {
|
||||||
&mut self,
|
let data = match turn {
|
||||||
player_num: usize,
|
Err(_timeout) => return PlayerAction::Timeout,
|
||||||
turn: RequestResult<Vec<u8>>,
|
|
||||||
) -> proto::PlayerAction {
|
|
||||||
let turn = match turn {
|
|
||||||
Err(_timeout) => return proto::PlayerAction::Timeout,
|
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
};
|
};
|
||||||
|
|
||||||
let action: proto::Action = match serde_json::from_slice(&turn) {
|
let action: proto::Action = match serde_json::from_slice(&data) {
|
||||||
Err(err) => return proto::PlayerAction::ParseError(err.to_string()),
|
Err(error) => return PlayerAction::ParseError { data, error },
|
||||||
Ok(action) => action,
|
Ok(action) => action,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,15 +100,51 @@ impl PwMatch {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|command| {
|
.map(|command| {
|
||||||
let res = self.match_state.execute_command(player_num, &command);
|
let res = self.match_state.execute_command(player_num, &command);
|
||||||
proto::PlayerCommand {
|
PlayerCommand {
|
||||||
command,
|
command,
|
||||||
error: res.err(),
|
error: res.err(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
proto::PlayerAction::Commands(commands)
|
PlayerAction::Commands(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log_player_action(&mut self, player_id: usize, player_action: PlayerAction) {
|
||||||
|
match player_action {
|
||||||
|
PlayerAction::ParseError { data, error } => {
|
||||||
|
// TODO: can this be handled better?
|
||||||
|
let command =
|
||||||
|
String::from_utf8(data).unwrap_or_else(|_| "<invalid utf-8>".to_string());
|
||||||
|
|
||||||
|
self.match_ctx.log(MatchLogMessage::BadCommand {
|
||||||
|
player_id: player_id as u32,
|
||||||
|
command,
|
||||||
|
error: error.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// TODO: handle other action types
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PlayerCommand {
|
||||||
|
pub command: proto::Command,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub error: Option<proto::CommandError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the action a player performed.
|
||||||
|
// TODO: can we name this better? Is this a "play"?
|
||||||
|
pub enum PlayerAction {
|
||||||
|
Timeout,
|
||||||
|
ParseError {
|
||||||
|
data: Vec<u8>,
|
||||||
|
error: serde_json::Error,
|
||||||
|
},
|
||||||
|
Commands(Vec<PlayerCommand>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_errors(action: PlayerAction) -> Option<PlayerAction> {
|
fn action_errors(action: PlayerAction) -> Option<PlayerAction> {
|
||||||
|
|
|
@ -49,31 +49,3 @@ pub enum CommandError {
|
||||||
OriginDoesNotExist,
|
OriginDoesNotExist,
|
||||||
DestinationDoesNotExist,
|
DestinationDoesNotExist,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct PlayerCommand {
|
|
||||||
pub command: Command,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub error: Option<CommandError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
#[serde(tag = "type", content = "value")]
|
|
||||||
pub enum PlayerAction {
|
|
||||||
Timeout,
|
|
||||||
ParseError(String),
|
|
||||||
Commands(Vec<PlayerCommand>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
#[serde(tag = "type", content = "content")]
|
|
||||||
pub enum ServerMessage {
|
|
||||||
/// Game state in current turn
|
|
||||||
GameState(State),
|
|
||||||
/// The action that was performed
|
|
||||||
PlayerAction(PlayerAction),
|
|
||||||
/// The game is over, and this is the concluding state.
|
|
||||||
FinalState(State),
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue