Refactor rust client
This commit is contained in:
198
src/main.rs
198
src/main.rs
@ -8,6 +8,7 @@ extern crate serde;
|
|||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
extern crate log4rs;
|
extern crate log4rs;
|
||||||
|
|
||||||
|
mod structs;
|
||||||
mod messages;
|
mod messages;
|
||||||
mod snake;
|
mod snake;
|
||||||
mod util;
|
mod util;
|
||||||
@ -19,6 +20,7 @@ use std::thread;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use messages::{ Inbound };
|
||||||
|
|
||||||
const HOST: &'static str = "snake.cygni.se";
|
const HOST: &'static str = "snake.cygni.se";
|
||||||
const PORT: i32 = 80;
|
const PORT: i32 = 80;
|
||||||
@ -58,66 +60,57 @@ struct Client {
|
|||||||
id_sender: mpsc::Sender<String>
|
id_sender: mpsc::Sender<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_msg(client: &mut Client, msg: &String) -> Result<(), ClientError> {
|
fn route_msg(client: &mut Client, str_msg: &String) -> Result<(), ClientError> {
|
||||||
let snake = &mut client.snake;
|
let snake = &mut client.snake;
|
||||||
|
let inbound_msg = try!(messages::parse_inbound_msg(str_msg));
|
||||||
|
|
||||||
if msg.contains(messages::GAME_ENDED) {
|
match inbound_msg {
|
||||||
let json_msg: messages::GameEnded = try!(serde_json::from_str(msg));
|
Inbound::GameEnded(msg) => {
|
||||||
snake.on_game_ended(&json_msg);
|
snake.on_game_ended(&msg);
|
||||||
|
if is_training_mode() {
|
||||||
if is_training_mode() {
|
try!(client.out.close(ws::CloseCode::Normal));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Inbound::TournamentEnded(msg) => {
|
||||||
|
snake.on_tournament_ended(&msg);
|
||||||
try!(client.out.close(ws::CloseCode::Normal));
|
try!(client.out.close(ws::CloseCode::Normal));
|
||||||
}
|
},
|
||||||
} else if msg.contains(messages::TOURNAMENT_ENDED) {
|
Inbound::MapUpdate(msg) => {
|
||||||
let json_msg: messages::TournamentEnded = try!(serde_json::from_str(msg));
|
let direction = maputil::direction_as_string(&snake.get_next_move(&msg));
|
||||||
snake.on_tournament_ended(&json_msg);
|
let response = try!(messages::create_register_move_msg(direction, msg));
|
||||||
try!(client.out.close(ws::CloseCode::Normal));
|
debug!(target: LOG_TARGET, "Responding with RegisterMove {:?}", response);
|
||||||
} else if msg.contains(messages::MAP_UPDATE) {
|
|
||||||
let json_msg: messages::MapUpdate = try!(serde_json::from_str(msg));
|
|
||||||
let direction = snake.get_next_move(&json_msg);
|
|
||||||
|
|
||||||
let response = messages::RegisterMove {
|
|
||||||
type_: String::from(messages::REGISTER_MOVE),
|
|
||||||
direction: maputil::direction_as_string(&direction),
|
|
||||||
gameTick: json_msg.gameTick,
|
|
||||||
receivingPlayerId: json_msg.receivingPlayerId,
|
|
||||||
gameId: json_msg.gameId
|
|
||||||
};
|
|
||||||
debug!(target: LOG_TARGET, "Responding with RegisterMove {:?}", response);
|
|
||||||
|
|
||||||
let response = try!(serde_json::to_string(&response));
|
|
||||||
try!(client.out.send(response));
|
|
||||||
} else if msg.contains(messages::SNAKE_DEAD) {
|
|
||||||
let json_msg: messages::SnakeDead = try!(serde_json::from_str(msg));
|
|
||||||
snake.on_snake_dead(&json_msg);
|
|
||||||
} else if msg.contains(messages::GAME_STARTING) {
|
|
||||||
let json_msg: messages::GameStarting = try!(serde_json::from_str(msg));
|
|
||||||
snake.on_game_starting(&json_msg);
|
|
||||||
} else if msg.contains(messages::PLAYER_REGISTERED) {
|
|
||||||
let json_msg: messages::PlayerRegistered = try!(serde_json::from_str(msg));
|
|
||||||
info!(target: LOG_TARGET, "Successfully registered player");
|
|
||||||
|
|
||||||
snake.on_player_registered(&json_msg);
|
|
||||||
|
|
||||||
if json_msg.gameMode == "TRAINING" {
|
|
||||||
let start_msg = messages::StartGame {
|
|
||||||
type_: String::from(messages::START_GAME)
|
|
||||||
};
|
|
||||||
debug!(target: LOG_TARGET, "Requesting a game start {:?}", start_msg);
|
|
||||||
|
|
||||||
let response = try!(serde_json::to_string(&start_msg));
|
|
||||||
try!(client.out.send(response));
|
try!(client.out.send(response));
|
||||||
};
|
},
|
||||||
|
Inbound::SnakeDead(msg) => {
|
||||||
|
snake.on_snake_dead(&msg);
|
||||||
|
},
|
||||||
|
Inbound::GameStarting(msg) => {
|
||||||
|
snake.on_game_starting(&msg);
|
||||||
|
},
|
||||||
|
Inbound::PlayerRegistered(msg) => {
|
||||||
|
info!(target: LOG_TARGET, "Successfully registered player");
|
||||||
|
snake.on_player_registered(&msg);
|
||||||
|
|
||||||
try!(client.out_sender.send(client.out.clone()));
|
if msg.gameMode == "TRAINING" {
|
||||||
try!(client.id_sender.send(json_msg.receivingPlayerId));
|
let response = try!(messages::create_start_game_msg());
|
||||||
} else if msg.contains(messages::INVALID_PLAYER_NAME) {
|
debug!(target: LOG_TARGET, "Requesting a game start {:?}", response);
|
||||||
let json_msg: messages::InvalidPlayerName = try!(serde_json::from_str(msg));
|
try!(client.out.send(response));
|
||||||
snake.on_invalid_playername(&json_msg);
|
};
|
||||||
} else if msg.contains(messages::HEART_BEAT_RESPONSE) {
|
|
||||||
// do nothing
|
info!(target: LOG_TARGET, "Starting heart beat");
|
||||||
let _: messages::InvalidPlayerName = try!(serde_json::from_str(msg));
|
try!(client.out_sender.send(client.out.clone()));
|
||||||
}
|
try!(client.id_sender.send(msg.receivingPlayerId));
|
||||||
|
},
|
||||||
|
Inbound::InvalidPlayerName(msg) => {
|
||||||
|
snake.on_invalid_playername(&msg);
|
||||||
|
},
|
||||||
|
Inbound::HeartBeatResponse(_) => {
|
||||||
|
// do nothing
|
||||||
|
},
|
||||||
|
Inbound::UnrecognizedMessage => {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -127,16 +120,15 @@ impl ws::Handler for Client {
|
|||||||
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
|
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
|
||||||
debug!(target: LOG_TARGET, "Connection to Websocket opened");
|
debug!(target: LOG_TARGET, "Connection to Websocket opened");
|
||||||
|
|
||||||
let message = messages::PlayRegistration {
|
let parse_msg = messages::create_play_registration_msg(self.snake.get_name());
|
||||||
type_: String::from(messages::REGISTER_PLAYER_MESSAGE_TYPE),
|
|
||||||
playerName: self.snake.get_name(),
|
|
||||||
gameSettings: messages::default_gamesettings()
|
|
||||||
};
|
|
||||||
|
|
||||||
info!(target: LOG_TARGET, "Registering player with message: {:?}", message);
|
if let Ok(response) = parse_msg {
|
||||||
|
info!(target: LOG_TARGET, "Registering player with message: {:?}", response);
|
||||||
let encoded_message = serde_json::to_string(&message).unwrap();
|
self.out.send(response)
|
||||||
self.out.send(encoded_message)
|
} else {
|
||||||
|
error!(target: LOG_TARGET, "Unable to create play registration message {:?}", parse_msg);
|
||||||
|
self.out.close(ws::CloseCode::Error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
|
fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
|
||||||
@ -173,43 +165,57 @@ fn start_websocket_thread(id_sender: mpsc::Sender<String>,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_heart_beat(id: String, out: Arc<ws::Sender>, done_receiver: mpsc::Receiver<()>) {
|
||||||
|
loop {
|
||||||
|
thread::sleep(Duration::from_secs(HEART_BEAT_S));
|
||||||
|
let rec = done_receiver.try_recv();
|
||||||
|
|
||||||
|
// if the channel is disconnected or a done message is sent, break the loop
|
||||||
|
if let Err(e) = rec {
|
||||||
|
if e == mpsc::TryRecvError::Disconnected {
|
||||||
|
debug!(target: LOG_TARGET, "Stopping heartbeat due to channel disconnecting");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!(target: LOG_TARGET, "Stopping heartbeat due to finished execution");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(target: LOG_TARGET, "Sending heartbeat request");
|
||||||
|
|
||||||
|
let id = id.clone();
|
||||||
|
let parsed_msg = messages::create_heart_beat_msg(id);
|
||||||
|
if let Ok(heart_beat) = parsed_msg {
|
||||||
|
let send_result = out.send(heart_beat);
|
||||||
|
if let Err(e) = send_result {
|
||||||
|
error!(target: LOG_TARGET, "Unable to send heartbeat, got error {:?}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!(target: LOG_TARGET, "Unable to parse heart beat message {:?}", parsed_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_channels(id_receiver: mpsc::Receiver<String>,
|
||||||
|
out_receiver: mpsc::Receiver<Arc<ws::Sender>>)
|
||||||
|
-> Result<(String, Arc<ws::Sender>), mpsc::RecvError> {
|
||||||
|
let id = try!(id_receiver.recv());
|
||||||
|
let out = try!(out_receiver.recv());
|
||||||
|
Ok((id, out))
|
||||||
|
}
|
||||||
|
|
||||||
fn start_heart_beat_thread(id_receiver: mpsc::Receiver<String>,
|
fn start_heart_beat_thread(id_receiver: mpsc::Receiver<String>,
|
||||||
out_receiver: mpsc::Receiver<Arc<ws::Sender>>,
|
out_receiver: mpsc::Receiver<Arc<ws::Sender>>,
|
||||||
done_receiver: mpsc::Receiver<()>) -> thread::JoinHandle<()> {
|
done_receiver: mpsc::Receiver<()>) -> thread::JoinHandle<()> {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let id = id_receiver.recv().unwrap();
|
let res = recv_channels(id_receiver, out_receiver);
|
||||||
let out = out_receiver.recv().unwrap();
|
|
||||||
|
|
||||||
debug!(target: LOG_TARGET, "Starting heartbeat");
|
if let Ok((id, out)) = res {
|
||||||
|
debug!(target: LOG_TARGET, "Starting heartbeat");
|
||||||
loop {
|
do_heart_beat(id, out, done_receiver);
|
||||||
thread::sleep(Duration::from_secs(HEART_BEAT_S));
|
} else {
|
||||||
let rec = done_receiver.try_recv();
|
error!(target: LOG_TARGET, "Unable to start heart beat, the channel has been closed.");
|
||||||
|
};
|
||||||
// if the channel is disconnected or a done message is sent, break the loop
|
|
||||||
if let Err(e) = rec {
|
|
||||||
if e == mpsc::TryRecvError::Disconnected {
|
|
||||||
debug!(target: LOG_TARGET, "Stopping heartbeat due to channel disconnecting");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug!(target: LOG_TARGET, "Stopping heartbeat due to finished execution");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let id = id.clone();
|
|
||||||
let heart_beat = messages::HeartBeatRequest {
|
|
||||||
type_: String::from( messages::HEART_BEAT_REQUEST ),
|
|
||||||
receivingPlayerId: id
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!(target: LOG_TARGET, "Sending heartbeat request");
|
|
||||||
let request = serde_json::to_string(&heart_beat).unwrap();
|
|
||||||
let send_result = out.send(request);
|
|
||||||
if let Err(e) = send_result {
|
|
||||||
error!(target: LOG_TARGET, "Unable to send heartbeat, got error {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use messages::{ Map, SnakeInfo };
|
use structs::{ Map, SnakeInfo };
|
||||||
use util;
|
use util;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
|
|||||||
228
src/messages.rs
228
src/messages.rs
@ -1,5 +1,7 @@
|
|||||||
#![allow(non_snake_case)]
|
use structs;
|
||||||
//inbound messages
|
use serde_json::{ from_str, to_string, Error };
|
||||||
|
|
||||||
|
// Inbound
|
||||||
pub const GAME_ENDED: &'static str =
|
pub const GAME_ENDED: &'static str =
|
||||||
"se.cygni.snake.api.event.GameEndedEvent";
|
"se.cygni.snake.api.event.GameEndedEvent";
|
||||||
pub const TOURNAMENT_ENDED: &'static str =
|
pub const TOURNAMENT_ENDED: &'static str =
|
||||||
@ -17,181 +19,87 @@ pub const INVALID_PLAYER_NAME: &'static str =
|
|||||||
pub const HEART_BEAT_RESPONSE: &'static str =
|
pub const HEART_BEAT_RESPONSE: &'static str =
|
||||||
"se.cygni.snake.api.request.HeartBeatResponse";
|
"se.cygni.snake.api.request.HeartBeatResponse";
|
||||||
|
|
||||||
//outbound messages
|
// Outbound
|
||||||
pub const REGISTER_PLAYER_MESSAGE_TYPE: &'static str =
|
const REGISTER_PLAYER_MESSAGE_TYPE: &'static str =
|
||||||
"se.cygni.snake.api.request.RegisterPlayer";
|
"se.cygni.snake.api.request.RegisterPlayer";
|
||||||
pub const START_GAME: &'static str =
|
const START_GAME: &'static str =
|
||||||
"se.cygni.snake.api.request.StartGame";
|
"se.cygni.snake.api.request.StartGame";
|
||||||
pub const REGISTER_MOVE: &'static str =
|
const REGISTER_MOVE: &'static str =
|
||||||
"se.cygni.snake.api.request.RegisterMove";
|
"se.cygni.snake.api.request.RegisterMove";
|
||||||
pub const HEART_BEAT_REQUEST: &'static str =
|
const HEART_BEAT_REQUEST: &'static str =
|
||||||
"se.cygni.snake.api.request.HeartBeatRequest";
|
"se.cygni.snake.api.request.HeartBeatRequest";
|
||||||
|
|
||||||
// Outbound messages
|
pub enum Inbound {
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
GameEnded(structs::GameEnded),
|
||||||
pub struct GameSettings {
|
TournamentEnded(structs::TournamentEnded),
|
||||||
pub width: String,
|
MapUpdate(structs::MapUpdate),
|
||||||
pub height: String,
|
SnakeDead(structs::SnakeDead),
|
||||||
pub maxNoofPlayers: u32,
|
GameStarting(structs::GameStarting),
|
||||||
pub startSnakeLength: u32,
|
PlayerRegistered(structs::PlayerRegistered),
|
||||||
pub timeInMsPerTick: u32,
|
InvalidPlayerName(structs::InvalidPlayerName),
|
||||||
pub obstaclesEnabled: bool,
|
HeartBeatResponse(structs::HeartBeatResponse),
|
||||||
pub foodEnabled: bool,
|
UnrecognizedMessage
|
||||||
pub edgeWrapsAround: bool,
|
|
||||||
pub headToTailConsumes: bool,
|
|
||||||
pub tailConsumeGrows: bool,
|
|
||||||
pub addFoodLikelihood: u32,
|
|
||||||
pub removeFoodLikelihood: u32,
|
|
||||||
pub addObstacleLikelihood: u32,
|
|
||||||
pub removeObstacleLikelihood: u32,
|
|
||||||
pub spontaneousGrowthEveryNWorldTick: u32,
|
|
||||||
pub trainingGame: bool,
|
|
||||||
pub pointsPerLength: u32,
|
|
||||||
pub pointsPerFood: u32,
|
|
||||||
pub pointsPerCausedDeath: u32,
|
|
||||||
pub pointsPerNibble: u32,
|
|
||||||
pub pointsLastSnakeLiving: u32,
|
|
||||||
pub noofRoundsTailProtectedAfterNibble: u32,
|
|
||||||
pub pointsSuicide: i32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
pub fn parse_inbound_msg(msg: &String) -> Result<Inbound, Error> {
|
||||||
pub struct PlayRegistration {
|
let msg: Inbound =
|
||||||
#[serde(rename="type")]
|
if msg.contains(GAME_ENDED) {
|
||||||
pub type_: String,
|
Inbound::GameEnded(try!(from_str(msg)))
|
||||||
pub playerName: String,
|
} else if msg.contains(TOURNAMENT_ENDED) {
|
||||||
pub gameSettings: GameSettings,
|
Inbound::TournamentEnded(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(MAP_UPDATE) {
|
||||||
|
Inbound::MapUpdate(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(SNAKE_DEAD) {
|
||||||
|
Inbound::SnakeDead(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(GAME_STARTING) {
|
||||||
|
Inbound::GameStarting(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(PLAYER_REGISTERED) {
|
||||||
|
Inbound::PlayerRegistered(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(INVALID_PLAYER_NAME) {
|
||||||
|
Inbound::InvalidPlayerName(try!(from_str(msg)))
|
||||||
|
} else if msg.contains(HEART_BEAT_RESPONSE) {
|
||||||
|
Inbound::HeartBeatResponse(try!(from_str(msg)))
|
||||||
|
} else {
|
||||||
|
Inbound::UnrecognizedMessage
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct RegisterMove {
|
pub fn create_play_registration_msg(name: String) -> Result<String, Error> {
|
||||||
#[serde(rename="type")]
|
to_string(&structs::PlayRegistration {
|
||||||
pub type_: String,
|
type_: String::from(REGISTER_PLAYER_MESSAGE_TYPE),
|
||||||
pub direction: String,
|
playerName: name,
|
||||||
pub gameTick: u32,
|
gameSettings: default_gamesettings()
|
||||||
pub receivingPlayerId: String,
|
})
|
||||||
pub gameId: String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
pub fn create_start_game_msg() -> Result<String, Error> {
|
||||||
pub struct StartGame {
|
to_string(&structs::StartGame {
|
||||||
#[serde(rename="type")]
|
type_: String::from(START_GAME)
|
||||||
pub type_: String,
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
pub fn create_register_move_msg(direction: String, request: structs::MapUpdate) -> Result<String, Error> {
|
||||||
pub struct HeartBeatRequest {
|
to_string(&structs::RegisterMove {
|
||||||
#[serde(rename="type")]
|
type_: String::from(REGISTER_MOVE),
|
||||||
pub type_: String,
|
direction: direction,
|
||||||
pub receivingPlayerId: String
|
gameTick: request.gameTick,
|
||||||
|
receivingPlayerId: request.receivingPlayerId,
|
||||||
|
gameId: request.gameId
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//Inbound messages
|
pub fn create_heart_beat_msg(id: String) -> Result<String, Error> {
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
to_string(&structs::HeartBeatRequest {
|
||||||
pub struct PlayerRegistered {
|
type_: String::from( HEART_BEAT_REQUEST ),
|
||||||
#[serde(rename="type")]
|
receivingPlayerId: id
|
||||||
pub type_: String,
|
})
|
||||||
pub gameId: String,
|
|
||||||
pub gameMode: String,
|
|
||||||
pub receivingPlayerId: String,
|
|
||||||
pub name: String,
|
|
||||||
pub gameSettings: GameSettings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
pub fn default_gamesettings() -> structs::GameSettings {
|
||||||
pub struct MapUpdate {
|
structs::GameSettings {
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub receivingPlayerId: String,
|
|
||||||
pub gameId: String,
|
|
||||||
pub gameTick: u32,
|
|
||||||
pub map: Map,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct InvalidPlayerName {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub reasonCode: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct GameEnded {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub receivingPlayerId: String,
|
|
||||||
pub playerWinnerId: String,
|
|
||||||
pub gameId: String,
|
|
||||||
pub gameTick: u32,
|
|
||||||
pub map: Map,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct SnakeDead {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub playerId: String,
|
|
||||||
pub x: u32,
|
|
||||||
pub y: u32,
|
|
||||||
pub gameId: String,
|
|
||||||
pub gameTick: u32,
|
|
||||||
pub deathReason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct GameStarting {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub receivingPlayerId: String,
|
|
||||||
pub gameId: String,
|
|
||||||
pub noofPlayers: u32,
|
|
||||||
pub width: u32,
|
|
||||||
pub height: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct HeartBeatResponse {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub receivingPlayerId: Option<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct TournamentEnded {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub playerWinnerId: String,
|
|
||||||
pub gameId: String,
|
|
||||||
pub gameResult: String,
|
|
||||||
pub tournamentName: String,
|
|
||||||
pub tournamentId: String,
|
|
||||||
pub gameTick: Option<i32>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Map {
|
|
||||||
#[serde(rename="type")]
|
|
||||||
pub type_: String,
|
|
||||||
pub width: i32,
|
|
||||||
pub height: i32,
|
|
||||||
pub worldTick: u32,
|
|
||||||
pub snakeInfos: Vec<SnakeInfo>,
|
|
||||||
pub foodPositions: Vec<i32>,
|
|
||||||
pub obstaclePositions: Vec<i32>,
|
|
||||||
pub receivingPlayerId: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
|
||||||
pub struct SnakeInfo {
|
|
||||||
pub name: String,
|
|
||||||
pub points: i32,
|
|
||||||
pub positions: Vec<i32>,
|
|
||||||
pub tailProtectedForGameTicks: u32,
|
|
||||||
pub id: String
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn default_gamesettings() -> GameSettings {
|
|
||||||
GameSettings {
|
|
||||||
width: String::from("MEDIUM"),
|
width: String::from("MEDIUM"),
|
||||||
height: String::from("MEDIUM"),
|
height: String::from("MEDIUM"),
|
||||||
maxNoofPlayers: 5,
|
maxNoofPlayers: 5,
|
||||||
|
|||||||
16
src/snake.rs
16
src/snake.rs
@ -1,4 +1,4 @@
|
|||||||
use messages;
|
use structs::{ MapUpdate, GameEnded, TournamentEnded, SnakeDead, GameStarting, PlayerRegistered, InvalidPlayerName};
|
||||||
use maputil::{ Direction };
|
use maputil::{ Direction };
|
||||||
use util::{ translate_positions };
|
use util::{ translate_positions };
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ impl Snake {
|
|||||||
String::from("rusty-snake")
|
String::from("rusty-snake")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_next_move(&self, msg: &messages::MapUpdate) -> Direction {
|
pub fn get_next_move(&self, msg: &MapUpdate) -> Direction {
|
||||||
info!(target: LOG_TARGET, "Game map updated, tick: {}", msg.gameTick);
|
info!(target: LOG_TARGET, "Game map updated, tick: {}", msg.gameTick);
|
||||||
|
|
||||||
let ref map = msg.map;
|
let ref map = msg.map;
|
||||||
@ -43,27 +43,27 @@ impl Snake {
|
|||||||
direction
|
direction
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_game_ended(&self, msg: &messages::GameEnded) {
|
pub fn on_game_ended(&self, msg: &GameEnded) {
|
||||||
info!(target: LOG_TARGET, "Game ended, the winner is: {:?}", msg.playerWinnerId);
|
info!(target: LOG_TARGET, "Game ended, the winner is: {:?}", msg.playerWinnerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_tournament_ended(&self, msg: &messages::TournamentEnded) {
|
pub fn on_tournament_ended(&self, msg: &TournamentEnded) {
|
||||||
info!(target: LOG_TARGET, "Game ended, the winner is: {:?}", msg.playerWinnerId);
|
info!(target: LOG_TARGET, "Game ended, the winner is: {:?}", msg.playerWinnerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_snake_dead(&self, msg: &messages::SnakeDead) {
|
pub fn on_snake_dead(&self, msg: &SnakeDead) {
|
||||||
info!(target: LOG_TARGET, "The snake died, reason was: {:?}", msg.deathReason);
|
info!(target: LOG_TARGET, "The snake died, reason was: {:?}", msg.deathReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_game_starting(&self, _: &messages::GameStarting) {
|
pub fn on_game_starting(&self, _: &GameStarting) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_player_registered(&self, _: &messages::PlayerRegistered) {
|
pub fn on_player_registered(&self, _: &PlayerRegistered) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_invalid_playername(&self, _: &messages::InvalidPlayerName) {
|
pub fn on_invalid_playername(&self, _: &InvalidPlayerName) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
162
src/structs.rs
Normal file
162
src/structs.rs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct GameSettings {
|
||||||
|
pub width: String,
|
||||||
|
pub height: String,
|
||||||
|
pub maxNoofPlayers: u32,
|
||||||
|
pub startSnakeLength: u32,
|
||||||
|
pub timeInMsPerTick: u32,
|
||||||
|
pub obstaclesEnabled: bool,
|
||||||
|
pub foodEnabled: bool,
|
||||||
|
pub edgeWrapsAround: bool,
|
||||||
|
pub headToTailConsumes: bool,
|
||||||
|
pub tailConsumeGrows: bool,
|
||||||
|
pub addFoodLikelihood: u32,
|
||||||
|
pub removeFoodLikelihood: u32,
|
||||||
|
pub addObstacleLikelihood: u32,
|
||||||
|
pub removeObstacleLikelihood: u32,
|
||||||
|
pub spontaneousGrowthEveryNWorldTick: u32,
|
||||||
|
pub trainingGame: bool,
|
||||||
|
pub pointsPerLength: u32,
|
||||||
|
pub pointsPerFood: u32,
|
||||||
|
pub pointsPerCausedDeath: u32,
|
||||||
|
pub pointsPerNibble: u32,
|
||||||
|
pub pointsLastSnakeLiving: u32,
|
||||||
|
pub noofRoundsTailProtectedAfterNibble: u32,
|
||||||
|
pub pointsSuicide: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct PlayRegistration {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub playerName: String,
|
||||||
|
pub gameSettings: GameSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct RegisterMove {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub direction: String,
|
||||||
|
pub gameTick: u32,
|
||||||
|
pub receivingPlayerId: String,
|
||||||
|
pub gameId: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct StartGame {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct HeartBeatRequest {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub receivingPlayerId: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct PlayerRegistered {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub gameId: String,
|
||||||
|
pub gameMode: String,
|
||||||
|
pub receivingPlayerId: String,
|
||||||
|
pub name: String,
|
||||||
|
pub gameSettings: GameSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct MapUpdate {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub receivingPlayerId: String,
|
||||||
|
pub gameId: String,
|
||||||
|
pub gameTick: u32,
|
||||||
|
pub map: Map,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct InvalidPlayerName {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub reasonCode: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct GameEnded {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub receivingPlayerId: String,
|
||||||
|
pub playerWinnerId: String,
|
||||||
|
pub gameId: String,
|
||||||
|
pub gameTick: u32,
|
||||||
|
pub map: Map,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct SnakeDead {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub playerId: String,
|
||||||
|
pub x: u32,
|
||||||
|
pub y: u32,
|
||||||
|
pub gameId: String,
|
||||||
|
pub gameTick: u32,
|
||||||
|
pub deathReason: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct GameStarting {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub receivingPlayerId: String,
|
||||||
|
pub gameId: String,
|
||||||
|
pub noofPlayers: u32,
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct HeartBeatResponse {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub receivingPlayerId: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct TournamentEnded {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub playerWinnerId: String,
|
||||||
|
pub gameId: String,
|
||||||
|
pub gameResult: String,
|
||||||
|
pub tournamentName: String,
|
||||||
|
pub tournamentId: String,
|
||||||
|
pub gameTick: Option<i32>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Map {
|
||||||
|
#[serde(rename="type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub width: i32,
|
||||||
|
pub height: i32,
|
||||||
|
pub worldTick: u32,
|
||||||
|
pub snakeInfos: Vec<SnakeInfo>,
|
||||||
|
pub foodPositions: Vec<i32>,
|
||||||
|
pub obstaclePositions: Vec<i32>,
|
||||||
|
pub receivingPlayerId: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
|
pub struct SnakeInfo {
|
||||||
|
pub name: String,
|
||||||
|
pub points: i32,
|
||||||
|
pub positions: Vec<i32>,
|
||||||
|
pub tailProtectedForGameTicks: u32,
|
||||||
|
pub id: String
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user