From 573ba69d810914c153a578747414b3d631e61bbc Mon Sep 17 00:00:00 2001 From: tom barrett Date: Thu, 12 Apr 2018 04:33:23 -0500 Subject: completely restructured code and fixed navigation bug --- src/astroid.rs | 19 ++---- src/bin/client.rs | 26 ++++----- src/bin/server.rs | 7 ++- src/client/dashboard.rs | 16 +++++ src/client/engines.rs | 49 ++++++++++++++++ src/client/mining.rs | 54 +++++++++++++++++ src/client/mod.rs | 4 ++ src/client/navigation.rs | 101 ++++++++++++++++++++++++++++++++ src/connection.rs | 42 +++++++------- src/dashboard.rs | 31 ---------- src/engines.rs | 123 --------------------------------------- src/lib.rs | 9 +-- src/mass.rs | 3 +- src/math.rs | 8 +++ src/mining.rs | 126 ---------------------------------------- src/module.rs | 22 +++++-- src/navigation.rs | 148 ----------------------------------------------- src/server/dashboard.rs | 18 ++++++ src/server/engines.rs | 78 +++++++++++++++++++++++++ src/server/mining.rs | 84 +++++++++++++++++++++++++++ src/server/mod.rs | 4 ++ src/server/navigation.rs | 54 +++++++++++++++++ src/ship.rs | 38 ++++++------ 23 files changed, 553 insertions(+), 511 deletions(-) create mode 100644 src/client/dashboard.rs create mode 100644 src/client/engines.rs create mode 100644 src/client/mining.rs create mode 100644 src/client/mod.rs create mode 100644 src/client/navigation.rs delete mode 100644 src/dashboard.rs delete mode 100644 src/engines.rs delete mode 100644 src/mining.rs delete mode 100644 src/navigation.rs create mode 100644 src/server/dashboard.rs create mode 100644 src/server/engines.rs create mode 100644 src/server/mining.rs create mode 100644 src/server/mod.rs create mode 100644 src/server/navigation.rs diff --git a/src/astroid.rs b/src/astroid.rs index ef1d401..f95e362 100644 --- a/src/astroid.rs +++ b/src/astroid.rs @@ -1,17 +1,15 @@ -use self::rand::distributions::Range; -use astroid::rand::distributions::Sample; - extern crate rand; extern crate serde_json; +use self::rand::distributions::Range; +use self::rand::distributions::Sample; + +use item::Item; use storage::Storage; -use astroid::rand::Rng; use mass::{Mass, MassType}; -use item::Item; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Astroid { - name : String, mass_type : MassType, position : (f64, f64, f64), velocity : (f64, f64, f64), @@ -20,10 +18,6 @@ pub struct Astroid { impl Astroid { pub fn new() -> Astroid { - let name : String = rand::thread_rng() - .gen_ascii_chars() - .take(8) - .collect(); let mut rng = rand::thread_rng(); let mut pr = Range::new(-50.0, 50.0); @@ -38,7 +32,6 @@ impl Astroid { resouces.push(Item::new("Iron", 1)) } Astroid { - name : name, mass_type : MassType::Astroid, position : position, velocity : velocity, @@ -48,10 +41,6 @@ impl Astroid { } impl Mass for Astroid { - fn name(&self) -> &String { - &self.name - } - fn recv_mass_type(&self) -> MassType { self.mass_type.clone() } diff --git a/src/bin/client.rs b/src/bin/client.rs index 7eb89ae..5460652 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -1,16 +1,16 @@ +extern crate space; +extern crate serde_json; + use std::io; use std::io::prelude::*; use std::io::BufReader; use std::net::TcpStream; -extern crate serde_json; - -extern crate space; -use space::mining::client_mining; -use space::engines::client_engines; -use space::dashboard::client_dashboard; -use space::navigation::client_navigation; -use space::module::Module; +use space::module::ModuleType; +use space::client::mining::client_mining; +use space::client::engines::client_engines; +use space::client::dashboard::client_dashboard; +use space::client::navigation::client_navigation; fn main() { let mut name = String::new(); @@ -31,7 +31,7 @@ fn main() { let mut recv = String::new(); buff_r.read_line(&mut recv).unwrap(); - let modules : Vec = serde_json::from_str(&recv.replace("\n","")).unwrap(); + let modules : Vec = serde_json::from_str(&recv.replace("\n","")).unwrap(); println!("Choose your module:"); for (i, module) in modules.iter().enumerate() { @@ -46,9 +46,9 @@ fn main() { stream.write(send.as_bytes()).unwrap(); match module { - Module::Dashboard => client_dashboard(buff_r), - Module::Engines => client_engines(stream, buff_r), - Module::Navigation => client_navigation(name, stream, buff_r), - Module::Mining => client_mining(stream, buff_r), + ModuleType::Dashboard => client_dashboard(buff_r), + ModuleType::Engines => client_engines(stream, buff_r), + ModuleType::Navigation => client_navigation(name, stream, buff_r), + ModuleType::Mining => client_mining(stream, buff_r), } } diff --git a/src/bin/server.rs b/src/bin/server.rs index f7aaffe..c5954b0 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -1,19 +1,20 @@ +extern crate space; + use std::thread::sleep; use std::time::Duration; use std::net::TcpListener; use std::collections::HashMap; -extern crate space; use space::mass::Mass; +use space::math::rand_name; use space::astroid::Astroid; use space::connection::Connection; - fn populate() -> HashMap> { let mut masses : HashMap> = HashMap::new(); for _ in 0..10 { - masses.insert("zz".to_string(), Box::new(Astroid::new())); + masses.insert(rand_name(), Box::new(Astroid::new())); } masses diff --git a/src/client/dashboard.rs b/src/client/dashboard.rs new file mode 100644 index 0000000..3776223 --- /dev/null +++ b/src/client/dashboard.rs @@ -0,0 +1,16 @@ +extern crate serde_json; + +use std::io::BufRead; +use std::io::BufReader; +use std::net::TcpStream; + +use ship::Ship; + +pub fn client_dashboard(mut buff_r : BufReader) { + loop { + let mut recv = String::new(); + buff_r.read_line(&mut recv).unwrap(); + let ship : Ship = serde_json::from_str(&recv).unwrap(); + println!("{:?}", ship); + } +} diff --git a/src/client/engines.rs b/src/client/engines.rs new file mode 100644 index 0000000..b6f5f93 --- /dev/null +++ b/src/client/engines.rs @@ -0,0 +1,49 @@ +extern crate termion; +extern crate serde_json; + +use std::thread::sleep; +use std::time::Duration; +use std::net::TcpStream; +use self::termion::async_stdin; +use std::io::{BufRead, BufReader}; +use std::io::{Read, Write, stdout}; +use self::termion::raw::IntoRawMode; + +pub fn client_engines(mut stream : TcpStream, mut buff_r : BufReader) { + let stdout = stdout(); + let mut stdout = stdout.lock().into_raw_mode().unwrap(); + let mut stdin = async_stdin().bytes(); + + loop { + let mut recv = String::new(); + buff_r.read_line(&mut recv).unwrap(); + let has_target = serde_json::from_str(&recv.replace("\n", "")).unwrap(); + + write!(stdout, "{}{}use numpad to freely move\n", termion::clear::All, termion::cursor::Goto(1, 1)).unwrap(); + write!(stdout, "{}+ : speedup", termion::cursor::Goto(1, 2)).unwrap(); + write!(stdout, "{}- : slowdown", termion::cursor::Goto(1, 3)).unwrap(); + write!(stdout, "{}q : quit", termion::cursor::Goto(1, 4)).unwrap(); + + if has_target { + write!(stdout, "{}c : mimic targets velocity vector", termion::cursor::Goto(1,5)).unwrap(); + write!(stdout, "{}t : accelerate torwards target", termion::cursor::Goto(1,6)).unwrap(); + } + + match stdin.next() { + Some(c) => { + let c = c.unwrap(); + let mut send = String::new(); + send.push(c as char); + if send.as_bytes() == b"q" { + break; + } + send.push_str("\n"); + stream.write(send.as_bytes()).unwrap(); + } + None => () + } + + stdout.flush().unwrap(); + sleep(Duration::from_millis(100)); + } +} diff --git a/src/client/mining.rs b/src/client/mining.rs new file mode 100644 index 0000000..44e7c30 --- /dev/null +++ b/src/client/mining.rs @@ -0,0 +1,54 @@ +extern crate termion; +extern crate serde_json; + +use std::net::TcpStream; +use self::termion::async_stdin; +use std::io::{BufReader, BufRead}; +use std::io::{stdout, Read, Write}; +use self::termion::raw::IntoRawMode; + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct ServerData { + has_astroid_target : bool, + is_within_range : bool, + mining_range : f64, + mining_status : bool, +} + +pub fn client_mining(mut stream : TcpStream, mut buff_r : BufReader) { + let stdout = stdout(); + let mut stdout = stdout.lock().into_raw_mode().unwrap(); + let mut stdin = async_stdin().bytes(); + + loop { + let mut recv = String::new(); + buff_r.read_line(&mut recv).unwrap(); + let data : ServerData = serde_json::from_str(&recv.replace("\n", "")).unwrap(); + + write!(stdout, "{}", termion::clear::All).unwrap(); + + match data.has_astroid_target { + true => match data.is_within_range { + true => write!(stdout, "{}Press F to begin mining.", termion::cursor::Goto(1,1)).unwrap(), + false => write!(stdout, "{}Astroid must be within range of {}.", termion::cursor::Goto(1,1), data.mining_range).unwrap(), + }, + false => write!(stdout, "{}Ship has no astroid targeted.", termion::cursor::Goto(1,1)).unwrap(), + } + + match stdin.next() { + Some(c) => { + let c = c.unwrap(); + let mut send = String::new(); + send.push(c as char); + if send.as_bytes() == b"q" { + break; + } + send.push_str("\n"); + stream.write(send.as_bytes()).unwrap(); + } + None => () + } + + stdout.flush().unwrap(); + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs new file mode 100644 index 0000000..baabf96 --- /dev/null +++ b/src/client/mod.rs @@ -0,0 +1,4 @@ +pub mod mining; +pub mod engines; +pub mod dashboard; +pub mod navigation; diff --git a/src/client/navigation.rs b/src/client/navigation.rs new file mode 100644 index 0000000..e5a5069 --- /dev/null +++ b/src/client/navigation.rs @@ -0,0 +1,101 @@ +extern crate termion; +extern crate itertools; +extern crate serde_json; + +use std::net::TcpStream; +use std::collections::BTreeMap; +use self::termion::async_stdin; +use self::itertools::Itertools; +use std::io::{BufRead, BufReader}; +use std::io::{stdout, Read, Write}; +use self::termion::raw::IntoRawMode; + +use mass::Mass; +use ship::Ship; +use math::distance; +use astroid::Astroid; + +pub fn client_navigation(name : String, mut stream : TcpStream, mut buff_r : BufReader){ + let stdout = stdout(); + let mut stdout = stdout.lock().into_raw_mode().unwrap(); + let mut stdin = async_stdin().bytes(); + + loop { + let mut recv = String::new(); + buff_r.read_line(&mut recv).unwrap(); + + let string_hashmap = recv.split(";"); + let mut masses : BTreeMap> = BTreeMap::new(); + for string_element in string_hashmap { + if string_element.len() <= 1 { + break; + } + let (string_name, string_mass) = string_element.split("@").next_tuple().unwrap(); + masses.insert(string_name.to_string(), build_mass(string_mass)); + } + + + write!(stdout, "{}{}Targets:", + termion::clear::All, + termion::cursor::Goto(1,1)).unwrap(); + + let ship = masses.remove(&name).unwrap().downcast::().unwrap(); + + for (i, (mass_name, mass)) in masses.iter().enumerate() { + + let target_data = match ship.recv_target() { + Some(target_name) => { + if &target_name == mass_name { + serde_json::to_string(&ship.recv_targeting_status()).unwrap() + } + else { + String::new() + } + } + None => String::new(), + }; + + write!(stdout, "{}{}) {} ({:.2}, {:.2}, {:.2}) Distance : {:.2} {}", + termion::cursor::Goto(1, 2 + i as u16), + i, + mass_name, + mass.position().0, + mass.position().1, + mass.position().2, + distance(mass.position(), ship.position()), + target_data + ).unwrap(); + } + + match stdin.next() { + Some(c) => { + let c = c.unwrap() as char; + if c == 'q' { + break; + } + else { + let i = c.to_digit(10).unwrap() as usize; + if i < masses.len() { + let mut send = String::new(); + send.push_str(masses.iter().nth(i).unwrap().0); + send.push_str("\n"); + stream.write(send.as_bytes()).unwrap(); + } + } + } + None => () + } + stdout.flush().unwrap(); + } +} + +fn build_mass(string_mass : &str) -> Box { + if string_mass.contains("Ship") { + let mass : Ship = serde_json::from_str(&string_mass).unwrap(); + return Box::new(mass) + } + else { + let mass : Astroid = serde_json::from_str(&string_mass).unwrap(); + return Box::new(mass) + } +} diff --git a/src/connection.rs b/src/connection.rs index 6ec2d16..91da04a 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,20 +1,20 @@ -use std::io::prelude::*; +extern crate serde_json; + use std::io::BufReader; +use std::io::prelude::*; use std::net::TcpStream; use std::collections::HashMap; -extern crate serde_json; - use ship::Ship; use mass::Mass; -use module::Module; +use module::ModuleType; pub struct Connection { - pub name : String, - pub module : Module, - pub stream : TcpStream, - pub buff_r : BufReader, - pub open : bool, + pub name : String, + pub module_type : ModuleType, + pub stream : TcpStream, + pub buff_r : BufReader, + pub open : bool, } impl Connection { @@ -25,7 +25,7 @@ impl Connection { buff_r.read_line(&mut recv).unwrap(); let name = &recv[..recv.find(":").unwrap()]; - let mass = masses.entry(name.to_string()).or_insert(Box::new(Ship::new(name, (0.0, 0.0, 0.0)))); + let mass = masses.entry(name.to_string()).or_insert(Box::new(Ship::new((0.0, 0.0, 0.0)))); let ship = mass.downcast_ref::().unwrap(); let modules = ship.recv_modules(); @@ -33,25 +33,25 @@ impl Connection { let mut recv = String::new(); buff_r.read_line(&mut recv).unwrap(); - let module : Module = serde_json::from_str(&recv.replace("\n","")).unwrap(); + let module_type : ModuleType = serde_json::from_str(&recv.replace("\n","")).unwrap(); stream.set_nonblocking(true).unwrap(); Connection { - name : String::from(name), - module : module, - stream : stream, - buff_r : buff_r, - open : true, + name : String::from(name), + module_type : module_type, + stream : stream, + buff_r : buff_r, + open : true, } } pub fn process(&mut self, mut masses : &mut HashMap>) { - self.open = match self.module { - Module::Engines => self.server_engines(&mut masses), - Module::Dashboard => self.server_dashboard(&mut masses), - Module::Navigation => self.server_navigation(&mut masses), - Module::Mining => self.server_mining(&mut masses), + self.open = match self.module_type { + ModuleType::Engines => self.server_engines(&mut masses), + ModuleType::Dashboard => self.server_dashboard(&mut masses), + ModuleType::Navigation => self.server_navigation(&mut masses), + ModuleType::Mining => self.server_mining(&mut masses), }; } } diff --git a/src/dashboard.rs b/src/dashboard.rs deleted file mode 100644 index 663818a..0000000 --- a/src/dashboard.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::io::BufReader; -use std::io::BufRead; -use std::net::TcpStream; -use std::io::Write; -use std::collections::HashMap; - -extern crate serde_json; - -use mass::Mass; -use ship::Ship; -use connection::Connection; - -pub fn client_dashboard(mut buff_r : BufReader) { - loop { - let mut recv = String::new(); - buff_r.read_line(&mut recv).unwrap(); - let ship : Ship = serde_json::from_str(&recv).unwrap(); - println!("{:?}", ship); - } -} - -impl Connection { - pub fn server_dashboard(&mut self, masses : &mut HashMap>) -> bool { - let ship = masses.get(&self.name).unwrap(); - let send = ship.serialize() + "\n"; - match self.stream.write(send.as_bytes()) { - Ok(_result) => true, - Err(_error) => false, - } - } -} diff --git a/src/engines.rs b/src/engines.rs deleted file mode 100644 index ce21e35..0000000 --- a/src/engines.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::net::TcpStream; -use termion::raw::IntoRawMode; -use termion::async_stdin; -use std::thread::sleep; -use std::io::{Read, Write, stdout}; -use std::time::Duration; -use std::io::{BufRead, BufReader}; -use std::collections::HashMap; - -extern crate termion; -extern crate serde_json; - -use ship::Ship; -use mass::Mass; -use targeting::TargetingStatus; -use connection::Connection; - -pub fn client_engines(mut stream : TcpStream, mut buff_r : BufReader) { - let stdout = stdout(); - let mut stdout = stdout.lock().into_raw_mode().unwrap(); - let mut stdin = async_stdin().bytes(); - - loop { - let mut recv = String::new(); - buff_r.read_line(&mut recv).unwrap(); - let has_target = serde_json::from_str(&recv.replace("\n", "")).unwrap(); - - write!(stdout, "{}{}use numpad to freely move\n", termion::clear::All, termion::cursor::Goto(1, 1)).unwrap(); - write!(stdout, "{}+ : speedup", termion::cursor::Goto(1, 2)).unwrap(); - write!(stdout, "{}- : slowdown", termion::cursor::Goto(1, 3)).unwrap(); - write!(stdout, "{}q : quit", termion::cursor::Goto(1, 4)).unwrap(); - - if has_target { - write!(stdout, "{}c : mimic targets velocity vector", termion::cursor::Goto(1,5)).unwrap(); - write!(stdout, "{}t : accelerate torwards target", termion::cursor::Goto(1,6)).unwrap(); - } - - match stdin.next() { - Some(c) => { - let c = c.unwrap(); - let mut send = String::new(); - send.push(c as char); - if send.as_bytes() == b"q" { - break; - } - send.push_str("\n"); - stream.write(send.as_bytes()).unwrap(); - } - None => () - } - - stdout.flush().unwrap(); - sleep(Duration::from_millis(100)); - } -} - -impl Connection { - pub fn server_engines(&mut self, masses : &mut HashMap>) -> bool { - let masses_clone = masses.clone(); - - let mass = masses.get_mut(&self.name).unwrap(); - let ship = mass.downcast_mut::().unwrap(); - - let targeted = ship.recv_targeting_status() == TargetingStatus::Targeted; - let send = serde_json::to_string(&targeted).unwrap() + "\n"; - - match self.stream.write(send.as_bytes()) { - Ok(_result) => (), - Err(_error) => return false, - } - - let mut acceleration = (0.0, 0.0, 0.0); - let mut recv = String::new(); - match self.buff_r.read_line(&mut recv) { - Ok(result) => match recv.as_bytes() { - b"5\n" => acceleration.0 += 0.1, - b"0\n" => acceleration.0 -= 0.1, - b"8\n" => acceleration.1 += 0.1, - b"2\n" => acceleration.1 -= 0.1, - b"4\n" => acceleration.2 += 0.1, - b"6\n" => acceleration.2 -= 0.1, - b"+\n" => ship.speedup(), - b"-\n" => ship.slow(), - b"c\n" => { - match ship.recv_target() { - Some(name) => { - let target = masses_clone.get(&name).unwrap(); - let d_v = target.recv_velocity(); - let m_v = ship.recv_velocity(); - acceleration = (d_v.0 - m_v.0, - d_v.1 - m_v.1, - d_v.2 - m_v.2); - }, - None => (), - } - }, - b"t\n" => { - match ship.recv_target() { - Some(name) => { - let target = masses_clone.get(&name).unwrap(); - let d_p = target.position(); - let m_p = ship.position(); - acceleration = ((d_p.0 - m_p.0) * 0.01, - (d_p.1 - m_p.1) * 0.01, - (d_p.2 - m_p.2) * 0.01); - }, - None => (), - } - }, - _ => { - if result == 0 { - return false - } - }, - }, - Err(_error) => (), - } - - ship.give_acceleration(acceleration); - - true - } -} diff --git a/src/lib.rs b/src/lib.rs index 923ddd0..d666cb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,19 +3,14 @@ extern crate serde_derive; #[macro_use] extern crate downcast; -extern crate termion; -extern crate time; - pub mod mass; pub mod item; pub mod ship; pub mod math; pub mod module; -pub mod mining; +pub mod client; +pub mod server; pub mod storage; pub mod astroid; -pub mod engines; -pub mod dashboard; pub mod targeting; pub mod connection; -pub mod navigation; diff --git a/src/mass.rs b/src/mass.rs index 186391b..5742f83 100644 --- a/src/mass.rs +++ b/src/mass.rs @@ -1,7 +1,8 @@ +extern crate serde; + use downcast::Any; pub trait Mass : Any { - fn name(&self) -> &String; fn recv_mass_type(&self) -> MassType; fn position(&self) -> (f64, f64, f64); fn serialize(&self) -> String; diff --git a/src/math.rs b/src/math.rs index 6766a60..127d4b4 100644 --- a/src/math.rs +++ b/src/math.rs @@ -1,3 +1,11 @@ +extern crate rand; + +use self::rand::Rng; + pub fn distance(l0 : (f64, f64, f64), l1 : (f64, f64, f64)) -> f64 { (((l1.0-l0.0).powf(2.0) + (l1.1-l0.1).powf(2.0) + (l1.2-l0.2).powf(2.0))).sqrt() } + +pub fn rand_name() -> String { + rand::thread_rng().gen_ascii_chars().take(8).collect() +} diff --git a/src/mining.rs b/src/mining.rs deleted file mode 100644 index df425e0..0000000 --- a/src/mining.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::io::{BufReader, BufRead}; -use std::collections::HashMap; -use std::net::TcpStream; -use std::io::{stdout, Read, Write}; -use termion::raw::IntoRawMode; -use termion::async_stdin; - -extern crate serde_json; -extern crate termion; - -use ship::Ship; -use math::distance; -use mass::{Mass, MassType}; -use connection::Connection; - -#[derive(Serialize, Deserialize, Debug, Clone)] -struct ServerData { - has_astroid_target : bool, - is_within_range : bool, - mining_range : f64, - mining_status : bool, -} - -pub fn client_mining(mut stream : TcpStream, mut buff_r : BufReader) { - let stdout = stdout(); - let mut stdout = stdout.lock().into_raw_mode().unwrap(); - let mut stdin = async_stdin().bytes(); - - loop { - let mut recv = String::new(); - buff_r.read_line(&mut recv).unwrap(); - let data : ServerData = serde_json::from_str(&recv.replace("\n", "")).unwrap(); - - write!(stdout, "{}", termion::clear::All).unwrap(); - - match data.has_astroid_target { - true => match data.is_within_range { - true => write!(stdout, "{}Press F to begin mining.", termion::cursor::Goto(1,1)).unwrap(), - false => write!(stdout, "{}Astroid must be within range of {}.", termion::cursor::Goto(1,1), data.mining_range).unwrap(), - }, - false => write!(stdout, "{}Ship has no astroid targeted.", termion::cursor::Goto(1,1)).unwrap(), - } - - match stdin.next() { - Some(c) => { - let c = c.unwrap(); - let mut send = String::new(); - send.push(c as char); - if send.as_bytes() == b"q" { - break; - } - send.push_str("\n"); - stream.write(send.as_bytes()).unwrap(); - } - None => () - } - - stdout.flush().unwrap(); - } -} - -impl Connection { - pub fn server_mining(&mut self, masses : &mut HashMap>) -> bool { - let masses_clone = masses.clone(); - let mass = masses.get_mut(&self.name).unwrap(); - let ship = mass.downcast_mut::().unwrap(); - - let target = match ship.recv_target() { - Some(name) => masses_clone.get(&name), - None => None, - }; - - let has_astroid_target = match target { - Some(target) => match target.recv_mass_type() { - MassType::Ship => false, - MassType::Astroid => true, - }, - None => false, - }; - - let is_within_range = match has_astroid_target { - true => match target { - Some(target) => match ship.recv_mining_range() > distance(ship.position(), target.position()) { - true => true, - false => false, - }, - None => false, - } - false => false, - }; - - let send = serde_json::to_string(&ServerData { - has_astroid_target : has_astroid_target, - is_within_range : is_within_range, - mining_range : ship.recv_mining_range(), - mining_status : ship.recv_mining_status(), - }).unwrap() + "\n"; - - match self.stream.write(send.as_bytes()) { - Ok(_result) => (), - Err(_error) => return false, - } - - let mut recv = String::new(); - match self.buff_r.read_line(&mut recv) { - Ok(result) => match recv.as_bytes() { - b"F\n" => { - if is_within_range { - match ship.recv_mining_status() { - true => ship.stop_mining(), - false => ship.start_mining(), - } - } - }, - _ => { - if result == 0 { - return false - } - }, - } - Err(_error) => (), - } - - true - } -} diff --git a/src/module.rs b/src/module.rs index 8d9a361..800f4d7 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,7 +1,21 @@ -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum Module { +use downcast::Any; + +pub trait Module : Any { + fn box_clone(&self) -> Box; +} + +impl Clone for Box { + fn clone(&self) -> Box { + self.box_clone() + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +pub enum ModuleType { + Mining, + Engines, Dashboard, Navigation, - Engines, - Mining, } + +downcast!(Module); diff --git a/src/navigation.rs b/src/navigation.rs deleted file mode 100644 index 1a4d0dd..0000000 --- a/src/navigation.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::collections::HashMap; -use std::net::TcpStream; -use std::io::{BufRead, BufReader}; -use std::io::{stdout, Read, Write}; -use termion::raw::IntoRawMode; -use termion::async_stdin; - -extern crate serde_json; -extern crate termion; - -use mass::Mass; -use ship::Ship; -use math::distance; -use astroid::Astroid; -use connection::Connection; - -pub fn client_navigation(name : String, mut stream : TcpStream, mut buff_r : BufReader){ - let stdout = stdout(); - let mut stdout = stdout.lock().into_raw_mode().unwrap(); - let mut stdin = async_stdin().bytes(); - - loop { - let mut recv = String::new(); - buff_r.read_line(&mut recv).unwrap(); - - let string_masses = recv.split(";"); - let mut masses : Vec> = Vec::new(); - for string_mass in string_masses { - if string_mass.len() <= 1 { - break; - } - masses.push(build_mass(string_mass)); - } - - let index = masses.iter().position(|ship| ship.name() == &name).unwrap(); - let ship = masses.remove(index).downcast::().unwrap(); - - write!(stdout, "{}{}Targets:", - termion::clear::All, - termion::cursor::Goto(1,1)).unwrap(); - - for (i, mass) in masses.iter().enumerate() { - - let target_data = match ship.recv_target() { - Some(name) => { - if &name == mass.name() { - serde_json::to_string(&ship.recv_targeting_status()).unwrap() - } - else { - String::new() - } - } - None => String::new(), - }; - - write!(stdout, "{}{}) {} ({:.2}, {:.2}, {:.2}) Distance : {:.2} {}", - termion::cursor::Goto(1, 2 + i as u16), - i, - mass.name(), - mass.position().0, - mass.position().1, - mass.position().2, - distance(mass.position(), ship.position()), - target_data - ).unwrap(); - } - - match stdin.next() { - Some(c) => { - let c = c.unwrap(); - let mut send = String::new(); - send.push(c as char); - if send.as_bytes() == b"q" { - break; - } - else { - let i = match send.parse::() { - Ok(num) => num, - Err(_err) => 100, - }; - if i < masses.len() { - send = masses[i].serialize(); - send.push_str("\n"); - stream.write(send.as_bytes()).unwrap(); - } - } - } - None => () - } - - stdout.flush().unwrap(); - } -} - -impl Connection { - pub fn server_navigation(&mut self, masses : &mut HashMap>) -> bool { - let masses_clone = masses.clone(); - let mass = masses.get_mut(&self.name).unwrap(); - let ship = mass.downcast_mut::().unwrap(); - - match ship.recv_target() { - Some(name) => { - let target = masses_clone.get(&name).unwrap(); - if distance(target.position(), ship.position()) > ship.recv_range() { - ship.give_target(None); - } - } - None => (), - } - - let within_range : Vec<&Box> = masses_clone.values().filter(|mass| - distance(ship.position(), mass.position()) < ship.recv_range()) - .collect(); - let mut send = String::new(); - for mass in within_range { - send.push_str(&mass.serialize()); - send.push_str(";"); - } - send.push_str("\n"); - match self.stream.write(send.as_bytes()) { - Ok(_result) => (), - Err(_error) => return false, - } - - let mut string_mass = String::new(); - match self.buff_r.read_line(&mut string_mass) { - Ok(_result) => (), - Err(_error) => (), - } - if string_mass.len() > 0 { - let target = build_mass(&string_mass); - let name = target.name().clone(); - ship.give_target(Some(name)); - } - true - } -} - -fn build_mass(string_mass : &str) -> Box { - if string_mass.contains("Ship") { - let mass : Ship = serde_json::from_str(&string_mass).unwrap(); - return Box::new(mass) - } - else { - let mass : Astroid = serde_json::from_str(&string_mass).unwrap(); - return Box::new(mass) - } -} diff --git a/src/server/dashboard.rs b/src/server/dashboard.rs new file mode 100644 index 0000000..d12ea35 --- /dev/null +++ b/src/server/dashboard.rs @@ -0,0 +1,18 @@ +extern crate serde_json; + +use std::io::Write; +use std::collections::HashMap; + +use mass::Mass; +use connection::Connection; + +impl Connection { + pub fn server_dashboard(&mut self, masses : &mut HashMap>) -> bool { + let ship = masses.get(&self.name).unwrap(); + let send = ship.serialize() + "\n"; + match self.stream.write(send.as_bytes()) { + Ok(_result) => true, + Err(_error) => false, + } + } +} diff --git a/src/server/engines.rs b/src/server/engines.rs new file mode 100644 index 0000000..ec55ee0 --- /dev/null +++ b/src/server/engines.rs @@ -0,0 +1,78 @@ +extern crate serde_json; + +use std::io::Write; +use std::io::BufRead; +use std::collections::HashMap; + +use ship::Ship; +use mass::Mass; +use connection::Connection; +use targeting::TargetingStatus; + +impl Connection { + pub fn server_engines(&mut self, masses : &mut HashMap>) -> bool { + let masses_clone = masses.clone(); + + let mass = masses.get_mut(&self.name).unwrap(); + let ship = mass.downcast_mut::().unwrap(); + + let targeted = ship.recv_targeting_status() == TargetingStatus::Targeted; + let send = serde_json::to_string(&targeted).unwrap() + "\n"; + + match self.stream.write(send.as_bytes()) { + Ok(_result) => (), + Err(_error) => return false, + } + + let mut acceleration = (0.0, 0.0, 0.0); + let mut recv = String::new(); + match self.buff_r.read_line(&mut recv) { + Ok(result) => match recv.as_bytes() { + b"5\n" => acceleration.0 += 0.1, + b"0\n" => acceleration.0 -= 0.1, + b"8\n" => acceleration.1 += 0.1, + b"2\n" => acceleration.1 -= 0.1, + b"4\n" => acceleration.2 += 0.1, + b"6\n" => acceleration.2 -= 0.1, + b"+\n" => ship.speedup(), + b"-\n" => ship.slow(), + b"c\n" => { + match ship.recv_target() { + Some(name) => { + let target = masses_clone.get(&name).unwrap(); + let d_v = target.recv_velocity(); + let m_v = ship.recv_velocity(); + acceleration = (d_v.0 - m_v.0, + d_v.1 - m_v.1, + d_v.2 - m_v.2); + }, + None => (), + } + }, + b"t\n" => { + match ship.recv_target() { + Some(name) => { + let target = masses_clone.get(&name).unwrap(); + let d_p = target.position(); + let m_p = ship.position(); + acceleration = ((d_p.0 - m_p.0) * 0.01, + (d_p.1 - m_p.1) * 0.01, + (d_p.2 - m_p.2) * 0.01); + }, + None => (), + } + }, + _ => { + if result == 0 { + return false + } + }, + }, + Err(_error) => (), + } + + ship.give_acceleration(acceleration); + + true + } +} diff --git a/src/server/mining.rs b/src/server/mining.rs new file mode 100644 index 0000000..9aa054f --- /dev/null +++ b/src/server/mining.rs @@ -0,0 +1,84 @@ +extern crate serde_json; + +use std::io::BufRead; +use std::io::Write; +use std::collections::HashMap; + +use ship::Ship; +use math::distance; +use mass::{Mass, MassType}; +use connection::Connection; + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct ServerData { + has_astroid_target : bool, + is_within_range : bool, + mining_range : f64, + mining_status : bool, +} + +impl Connection { + pub fn server_mining(&mut self, masses : &mut HashMap>) -> bool { + let masses_clone = masses.clone(); + let mass = masses.get_mut(&self.name).unwrap(); + let ship = mass.downcast_mut::().unwrap(); + + let target = match ship.recv_target() { + Some(name) => masses_clone.get(&name), + None => None, + }; + + let has_astroid_target = match target { + Some(target) => match target.recv_mass_type() { + MassType::Ship => false, + MassType::Astroid => true, + }, + None => false, + }; + + let is_within_range = match has_astroid_target { + true => match target { + Some(target) => match ship.recv_mining_range() > distance(ship.position(), target.position()) { + true => true, + false => false, + }, + None => false, + } + false => false, + }; + + let send = serde_json::to_string(&ServerData { + has_astroid_target : has_astroid_target, + is_within_range : is_within_range, + mining_range : ship.recv_mining_range(), + mining_status : ship.recv_mining_status(), + }).unwrap() + "\n"; + + match self.stream.write(send.as_bytes()) { + Ok(_result) => (), + Err(_error) => return false, + } + + let mut recv = String::new(); + match self.buff_r.read_line(&mut recv) { + Ok(result) => match recv.as_bytes() { + b"F\n" => { + if is_within_range { + match ship.recv_mining_status() { + true => ship.stop_mining(), + false => ship.start_mining(), + } + } + }, + _ => { + if result == 0 { + return false + } + }, + } + Err(_error) => (), + } + + true + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..baabf96 --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,4 @@ +pub mod mining; +pub mod engines; +pub mod dashboard; +pub mod navigation; diff --git a/src/server/navigation.rs b/src/server/navigation.rs new file mode 100644 index 0000000..f75c2b7 --- /dev/null +++ b/src/server/navigation.rs @@ -0,0 +1,54 @@ +extern crate serde_json; + +use std::io::Write; +use std::io::BufRead; +use std::collections::HashMap; + +use mass::Mass; +use ship::Ship; +use math::distance; +use connection::Connection; + +impl Connection { + pub fn server_navigation(&mut self, masses : &mut HashMap>) -> bool { + let masses_clone = masses.clone(); + let mass = masses.get_mut(&self.name).unwrap(); + let ship = mass.downcast_mut::().unwrap(); + + match ship.recv_target() { + Some(name) => { + let target = masses_clone.get(&name).unwrap(); + if distance(target.position(), ship.position()) > ship.recv_range() { + ship.give_target(None); + } + } + None => (), + } + + let within_range : HashMap<&String, &Box> = masses_clone.iter().filter(|&(_, mass)| + distance(ship.position(), mass.position()) < ship.recv_range()) + .collect(); + let mut send = String::new(); + for (name, mass) in within_range { + send.push_str(name); + send.push_str("@"); + send.push_str(&mass.serialize()); + send.push_str(";"); + } + send.push_str("\n"); + match self.stream.write(send.as_bytes()) { + Ok(_result) => (), + Err(_error) => return false, + } + + let mut recv = String::new(); + match self.buff_r.read_line(&mut recv) { + Ok(_result) => (), + Err(_error) => (), + } + if recv.len() > 0 { + ship.give_target(Some(recv.replace("\n", ""))); + } + true + } +} diff --git a/src/ship.rs b/src/ship.rs index cfe913e..403b4ed 100644 --- a/src/ship.rs +++ b/src/ship.rs @@ -1,43 +1,48 @@ -use std::time::SystemTime; - extern crate serde_json; -use module::Module; +use std::time::SystemTime; +//use std::collections::HashMap; + +use storage::Storage; use mass::{Mass, MassType}; +//use module::{Module, ModuleType}; +use module::ModuleType; use targeting::{Targeting, TargetingStatus}; -use storage::Storage; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Ship { - name : String, mass_type : MassType, position : (f64, f64, f64), velocity : (f64, f64, f64), range : f64, - modules : Vec, - targeting : Targeting, + modules : Vec, mining : Mining, + targeting : Targeting, +// modules : HashMap>, storage : Storage, } impl Ship { - pub fn new(name : &str, position : (f64, f64, f64)) -> Ship { + pub fn new(position : (f64, f64, f64)) -> Ship { let mut modules = Vec::new(); - modules.push(Module::Navigation); - modules.push(Module::Engines); - modules.push(Module::Dashboard); - modules.push(Module::Mining); + modules.push(ModuleType::Navigation); + modules.push(ModuleType::Engines); + modules.push(ModuleType::Dashboard); + modules.push(ModuleType::Mining); + +// let mut modules : HashMap> = HashMap::new(); +// modules.insert(ModuleType::Navigation, Targeting::new()); +// modules.insert(ModuleType::Mining, Mining::new()); Ship { - name : String::from(name), mass_type : MassType::Ship, position : position, velocity : (0.0, 0.0, 0.0), range : 100.0, modules : modules, - targeting : Targeting::new(), mining : Mining::new(), + targeting : Targeting::new(), storage : Storage::new(Vec::new()), } } @@ -70,7 +75,6 @@ impl Ship { self.velocity.1 *= 1.05; self.velocity.2 *= 1.05; } - pub fn start_mining(&mut self) { self.mining.start() } @@ -109,10 +113,6 @@ impl Ship { } impl Mass for Ship { - fn name(&self) -> &String { - &self.name - } - fn recv_mass_type(&self) -> MassType { self.mass_type.clone() } -- cgit v1.2.3