From f617213b4a48d73acd245580f8551a7c37ce9ad8 Mon Sep 17 00:00:00 2001 From: tom barrett Date: Sun, 10 Feb 2019 03:55:05 -0600 Subject: added vector math and tractorbeam module --- src/bin/client.rs | 2 + src/client/mod.rs | 1 + src/client/navigation.rs | 11 ++---- src/client/tractorbeam.rs | 70 +++++++++++++++++++++++++++++++++++ src/mass.rs | 87 +++++++++++++++++++++++++++----------------- src/math.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++-- src/modules/engines.rs | 52 +++++++++----------------- src/modules/mod.rs | 1 + src/modules/navigation.rs | 10 ++--- src/modules/tractorbeam.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/modules/types.rs | 1 + src/server/connection.rs | 1 + src/server/mining.rs | 8 ++-- src/server/mod.rs | 1 + src/server/navigation.rs | 5 +-- src/server/tractorbeam.rs | 70 +++++++++++++++++++++++++++++++++++ 16 files changed, 409 insertions(+), 92 deletions(-) create mode 100644 src/client/tractorbeam.rs create mode 100644 src/modules/tractorbeam.rs create mode 100644 src/server/tractorbeam.rs diff --git a/src/bin/client.rs b/src/bin/client.rs index e452492..ef5faff 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -17,6 +17,7 @@ use space::client::engines::client_engines; use space::client::mining::client_mining; use space::client::navigation::client_navigation; use space::client::refinery::client_refinery; +use space::client::tractorbeam::client_tractorbeam; use space::modules::types::ModuleType; #[derive(Debug, Deserialize)] @@ -85,6 +86,7 @@ fn main() { ModuleType::Engines => client_engines(stream, buff_r), ModuleType::Refinery => client_refinery(stream, buff_r), ModuleType::Navigation => client_navigation(name, stream, buff_r), + ModuleType::Tractorbeam => client_tractorbeam(stream, buff_r), ModuleType::Construction => client_construction(stream, buff_r), } } diff --git a/src/client/mod.rs b/src/client/mod.rs index 530e2de..9045e90 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -4,3 +4,4 @@ pub mod engines; pub mod mining; pub mod navigation; pub mod refinery; +pub mod tractorbeam; diff --git a/src/client/navigation.rs b/src/client/navigation.rs index 0ab25c6..1f2ed06 100644 --- a/src/client/navigation.rs +++ b/src/client/navigation.rs @@ -9,7 +9,6 @@ use std::io::{BufRead, BufReader}; use std::net::TcpStream; use crate::mass::{Mass, MassType}; -use crate::math::distance; use crate::modules::navigation::Navigation; pub fn client_navigation(name: String, mut stream: TcpStream, mut buff_r: BufReader) { @@ -38,14 +37,12 @@ pub fn client_navigation(name: String, mut stream: TcpStream, mut buff_r: BufRea let target_data = get_target_status(&navigation, &mass_name); write!( stdout, - "{}{}) {} ({:.2}, {:.2}, {:.2}) Distance : {:.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), + mass.position, + mass.position.distance_from(ship.position.clone()), target_data ) .unwrap(); @@ -79,6 +76,6 @@ fn get_target_status(navigation: &Navigation, mass_name: &str) -> String { String::new() } } - _ => String::new(), + None => String::new(), } } diff --git a/src/client/tractorbeam.rs b/src/client/tractorbeam.rs new file mode 100644 index 0000000..e9e60b2 --- /dev/null +++ b/src/client/tractorbeam.rs @@ -0,0 +1,70 @@ +extern crate serde_json; +extern crate termion; + +use self::termion::async_stdin; +use self::termion::raw::IntoRawMode; +use std::io::{stdout, Read, Write}; +use std::io::{BufRead, BufReader}; +use std::net::TcpStream; + +use crate::modules::tractorbeam::TractorbeamStatus; +use crate::server::tractorbeam::TractorbeamData; + +pub fn client_tractorbeam(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: TractorbeamData = serde_json::from_str(&recv.replace("\n", "")).unwrap(); + + write!(stdout, "{}", termion::clear::All).unwrap(); + + let clear = termion::cursor::Goto(1, 1); + + if data.has_target { + match data.status { + TractorbeamStatus::None => write!( + stdout, + "{}Press o to pull, p to push, t to bring to 5m.", + clear + ) + .unwrap(), + TractorbeamStatus::Push => write!( + stdout, + "{}Press o to pull, p to stop pushing, t to bring to 5m.", + clear + ) + .unwrap(), + TractorbeamStatus::Pull => write!( + stdout, + "{}Press o to stop pulling, p to push, t to bring to 5m.", + clear + ) + .unwrap(), + TractorbeamStatus::Bring => write!( + stdout, + "{}Press o to pulling, p to push, t to stop bringing to 5m.", + clear + ) + .unwrap(), + }; + } else { + write!(stdout, "{}You have no target.", clear).unwrap(); + } + + if let Some(c) = stdin.next() { + 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_all(send.as_bytes()).unwrap(); + } + stdout.flush().unwrap(); + } +} diff --git a/src/mass.rs b/src/mass.rs index db97d49..14b0c83 100644 --- a/src/mass.rs +++ b/src/mass.rs @@ -4,20 +4,46 @@ use self::rand::distributions::Uniform; use self::rand::Rng; use crate::item::Item; +use crate::math::Vector; use crate::modules::construction::Construction; use crate::modules::dashboard::Dashboard; use crate::modules::engines::Engines; use crate::modules::mining::Mining; use crate::modules::navigation::Navigation; use crate::modules::refinery::Refinery; +use crate::modules::tractorbeam::Tractorbeam; use crate::modules::types::ModuleType; use crate::storage::Storage; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Mass { pub mass_type: MassType, - pub position: (f64, f64, f64), - pub velocity: (f64, f64, f64), + pub position: Vector, + pub velocity: Vector, + pub effects: Effects, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct Effects { + acceleration: Vector, +} + +impl Effects { + pub fn new() -> Effects { + Effects { + acceleration: Vector::default(), + } + } + + pub fn give_acceleration(&mut self, acceleration: Vector) { + self.acceleration += acceleration; + } + + pub fn take_acceleration(&mut self) -> Vector { + let acceleration = self.acceleration.clone(); + self.acceleration = Vector::default(); + acceleration + } } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -29,6 +55,7 @@ pub enum MassType { refinery: Option, dashboard: Option, navigation: Option, + tractorbeam: Option, construction: Option, }, Astroid { @@ -47,18 +74,7 @@ impl Mass { let mut rng = rand::thread_rng(); let p_range = Uniform::new(-50.0, 50.0); - let position = ( - rng.sample(p_range), - rng.sample(p_range), - rng.sample(p_range), - ); - let v_range = Uniform::new(-0.5, 0.5); - let velocity = ( - rng.sample(v_range), - rng.sample(v_range), - rng.sample(v_range), - ); let mut resources = Vec::new(); for _ in 0..rng.gen_range(0, 20) { @@ -71,8 +87,17 @@ impl Mass { Mass { mass_type: astroid, - position, - velocity, + position: Vector::new(( + rng.sample(p_range), + rng.sample(p_range), + rng.sample(p_range), + )), + velocity: Vector::new(( + rng.sample(v_range), + rng.sample(v_range), + rng.sample(v_range), + )), + effects: Effects::new(), } } @@ -83,36 +108,36 @@ impl Mass { refinery: Some(Refinery::new()), dashboard: Some(Dashboard::new()), navigation: Some(Navigation::new()), + tractorbeam: Some(Tractorbeam::new()), construction: Some(Construction::new()), storage: Storage::new(Vec::new()), }; Mass { mass_type: ship, - position: (0.0, 0.0, 0.0), - velocity: (0.0, 0.0, 0.0), + position: Vector::default(), + velocity: Vector::default(), + effects: Effects::new(), } } - pub fn new_item(item: Item, position: (f64, f64, f64), velocity: (f64, f64, f64)) -> Mass { + pub fn new_item(item: Item, position: Vector, velocity: Vector) -> Mass { Mass { mass_type: MassType::Item { item }, position, velocity, + effects: Effects::new(), } } - pub fn new_station( - module_type: ModuleType, - position: (f64, f64, f64), - velocity: (f64, f64, f64), - ) -> Mass { + pub fn new_station(module_type: ModuleType, position: Vector, velocity: Vector) -> Mass { let mass_type = MassType::Station { module_type }; Mass { mass_type, position, velocity, + effects: Effects::new(), } } @@ -123,12 +148,12 @@ impl Mass { modules.push(ModuleType::Refinery); modules.push(ModuleType::Dashboard); modules.push(ModuleType::Navigation); + modules.push(ModuleType::Tractorbeam); modules.push(ModuleType::Construction); modules } pub fn process(&mut self) { - let mut acceleration = (0.0, 0.0, 0.0); if let MassType::Ship { ref mut navigation, ref mut engines, @@ -142,18 +167,12 @@ impl Mass { refinery.as_mut().unwrap().process(); navigation.as_mut().unwrap().process(); construction.as_mut().unwrap().process(); - acceleration = engines.as_mut().unwrap().recv_acceleration(); + self.effects + .give_acceleration(engines.as_mut().unwrap().recv_acceleration()) } - self.accelerate(acceleration); - self.position.0 += self.velocity.0; - self.position.1 += self.velocity.1; - self.position.2 += self.velocity.2; - } - pub fn accelerate(&mut self, acceleration: (f64, f64, f64)) { - self.velocity.0 += acceleration.0; - self.velocity.1 += acceleration.1; - self.velocity.2 += acceleration.2; + self.velocity += self.effects.take_acceleration(); + self.position += self.velocity.clone(); } pub fn has_minerals(&self) -> bool { diff --git a/src/math.rs b/src/math.rs index 689ee65..0816149 100644 --- a/src/math.rs +++ b/src/math.rs @@ -4,13 +4,96 @@ use self::rand::distributions::Alphanumeric; use self::rand::Rng; use std::iter::repeat; -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 { repeat(()) .map(|()| rand::thread_rng().sample(Alphanumeric)) .take(8) .collect() } + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct Vector { + pub a: f64, + pub b: f64, + pub c: f64, +} + +impl Vector { + pub fn new(v: (f64, f64, f64)) -> Vector { + Vector { + a: v.0, + b: v.1, + c: v.2, + } + } + + pub fn distance_from(&self, other: Vector) -> f64 { + ((self.a - other.a).powf(2.0) + (self.b - other.b).powf(2.0) + (self.c - other.c).powf(2.0)) + .sqrt() + } + + pub fn unitize(&self) -> Vector { + let denominator = self.magnitude(); + Vector { + a: self.a / denominator, + b: self.b / denominator, + c: self.c / denominator, + } + } + + pub fn magnitude(&self) -> f64 { + (self.a.powf(2.0) + self.b.powf(2.0) + self.c.powf(2.0)).sqrt() + } +} + +impl std::fmt::Display for Vector { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "({:.2}, {:.2}, {:.2})", self.a, self.b, self.c) + } +} + +impl std::ops::Add for Vector { + type Output = Vector; + + fn add(self, other: Vector) -> Vector { + Vector { + a: self.a + other.a, + b: self.b + other.b, + c: self.c + other.c, + } + } +} + +impl std::ops::Sub for Vector { + type Output = Vector; + + fn sub(self, other: Vector) -> Vector { + Vector { + a: self.a - other.a, + b: self.b - other.b, + c: self.c - other.c, + } + } +} + +impl std::ops::Mul for Vector { + type Output = Vector; + + fn mul(self, other: f64) -> Vector { + Vector { + a: self.a * other, + b: self.b * other, + c: self.c * other, + } + } +} + +impl std::ops::AddAssign for Vector { + fn add_assign(&mut self, other: Vector) { + *self = Vector { + a: self.a + other.a, + b: self.b + other.b, + c: self.c + other.c, + } + } +} diff --git a/src/modules/engines.rs b/src/modules/engines.rs index a930847..f319ee5 100644 --- a/src/modules/engines.rs +++ b/src/modules/engines.rs @@ -1,64 +1,48 @@ use crate::mass::Mass; +use crate::math::Vector; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct Engines { - acceleration: (f64, f64, f64), + acceleration: Vector, } impl Engines { pub fn new() -> Engines { Engines { - acceleration: (0.0, 0.0, 0.0), + acceleration: Vector::default(), } } - pub fn recv_acceleration(&mut self) -> (f64, f64, f64) { - let acceleration = self.acceleration; - self.acceleration = (0.0, 0.0, 0.0); + pub fn recv_acceleration(&mut self) -> Vector { + let acceleration = self.acceleration.clone(); + self.acceleration = Vector::default(); acceleration } pub fn give_client_data(&mut self, ship: &Mass, target: Option<&Mass>, data: String) { - let mut acceleration = (0.0, 0.0, 0.0); + let mut acceleration = Vector::default(); match data.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" => { - let m_v = ship.velocity; - acceleration = (m_v.0 * 0.05, m_v.1 * 0.05, m_v.2 * 0.05); - } + b"5\n" => acceleration.a += 0.1, + b"0\n" => acceleration.a -= 0.1, + b"8\n" => acceleration.b += 0.1, + b"2\n" => acceleration.b -= 0.1, + b"4\n" => acceleration.c += 0.1, + b"6\n" => acceleration.c -= 0.1, + b"+\n" => acceleration = ship.velocity.clone() * 0.05, b"-\n" => { - let m_v = ship.velocity; - acceleration = ( - -1.0 * m_v.0 * 0.05, - -1.0 * m_v.1 * 0.05, - -1.0 * m_v.2 * 0.05, - ); + acceleration = ship.velocity.clone() * -1.05; } b"s\n" => { - let m_v = ship.velocity; - acceleration = (-1.0 * m_v.0, -1.0 * m_v.1, -1.0 * m_v.2); + acceleration = ship.velocity.clone() * -1.0; } b"c\n" => { if let Some(target) = target { - let d_v = target.velocity; - let m_v = ship.velocity; - acceleration = (d_v.0 - m_v.0, d_v.1 - m_v.1, d_v.2 - m_v.2); + acceleration = target.velocity.clone() - ship.velocity.clone(); } } b"t\n" => { if let Some(target) = target { - 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, - ); + acceleration = (target.position.clone() - ship.position.clone()) * 0.01; } } _ => (), diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 3929e24..15c161b 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -4,4 +4,5 @@ pub mod engines; pub mod mining; pub mod navigation; pub mod refinery; +pub mod tractorbeam; pub mod types; diff --git a/src/modules/navigation.rs b/src/modules/navigation.rs index 11f3e94..03a9ca5 100644 --- a/src/modules/navigation.rs +++ b/src/modules/navigation.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::time::SystemTime; use crate::mass::Mass; -use crate::math::distance; +use crate::math::Vector; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum NavigationStatus { @@ -52,14 +52,10 @@ impl Navigation { self.target_name = Some(target_name); } - pub fn verify_target( - &mut self, - ship_position: (f64, f64, f64), - masses: &HashMap, - ) { + pub fn verify_target(&mut self, ship_position: Vector, masses: &HashMap) { if let Some(name) = self.target_name.clone() { let target = masses.get(&name).unwrap(); - if distance(target.position, ship_position) > self.range { + if target.position.distance_from(ship_position) > self.range { self.target_name = None; self.status = NavigationStatus::None; } diff --git a/src/modules/tractorbeam.rs b/src/modules/tractorbeam.rs new file mode 100644 index 0000000..1ddc7d0 --- /dev/null +++ b/src/modules/tractorbeam.rs @@ -0,0 +1,90 @@ +use crate::mass::Mass; +use crate::math::Vector; + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct Tractorbeam { + pub status: TractorbeamStatus, + strength: f64, + desired_distance: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum TractorbeamStatus { + None, + Push, + Pull, + Bring, +} + +impl Default for TractorbeamStatus { + fn default() -> Self { + TractorbeamStatus::None + } +} + +impl Tractorbeam { + pub fn new() -> Tractorbeam { + Tractorbeam { + status: TractorbeamStatus::None, + strength: 0.1, + desired_distance: None, + } + } + + pub fn toggle_pull(&mut self) { + self.status = match self.status { + TractorbeamStatus::None => TractorbeamStatus::Pull, + TractorbeamStatus::Push => TractorbeamStatus::Pull, + TractorbeamStatus::Bring => TractorbeamStatus::Pull, + TractorbeamStatus::Pull => TractorbeamStatus::None, + } + } + + pub fn toggle_push(&mut self) { + self.status = match self.status { + TractorbeamStatus::None => TractorbeamStatus::Push, + TractorbeamStatus::Pull => TractorbeamStatus::Push, + TractorbeamStatus::Bring => TractorbeamStatus::Push, + TractorbeamStatus::Push => TractorbeamStatus::None, + } + } + + pub fn toggle_bring(&mut self, desired_distance: f64) { + self.desired_distance = Some(desired_distance); + self.status = match self.status { + TractorbeamStatus::None => TractorbeamStatus::Bring, + TractorbeamStatus::Pull => TractorbeamStatus::Bring, + TractorbeamStatus::Push => TractorbeamStatus::Bring, + TractorbeamStatus::Bring => TractorbeamStatus::None, + } + } + + pub fn off(&mut self) { + self.status = TractorbeamStatus::None; + } + + pub fn get_acceleration(&self, ship: Mass, target: Mass) -> Vector { + let acceleration = ship.position.clone() - target.position.clone(); + match self.status { + TractorbeamStatus::Push => acceleration.unitize() * -0.05, + TractorbeamStatus::Pull => acceleration.unitize() * 0.05, + TractorbeamStatus::Bring => match self.desired_distance { + Some(desired_distance) => { + if desired_distance > ship.position.distance_from(target.position) { + acceleration.unitize() * -0.05 + //some sort of velocity limiter + //if target.speed_torwards(ship) < 10.0 { + // acceleration.unitize() * -0.05 + //} else { + // Vector::default() + //} + } else { + acceleration.unitize() * 0.05 + } + } + None => Vector::default(), + }, + TractorbeamStatus::None => Vector::default(), + } + } +} diff --git a/src/modules/types.rs b/src/modules/types.rs index 17e7c6c..91e41dc 100644 --- a/src/modules/types.rs +++ b/src/modules/types.rs @@ -5,5 +5,6 @@ pub enum ModuleType { Refinery, Dashboard, Navigation, + Tractorbeam, Construction, } diff --git a/src/server/connection.rs b/src/server/connection.rs index 4fed2b6..662e33d 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -52,6 +52,7 @@ impl ServerConnection { ModuleType::Refinery => self.server_refinery(&mut masses), ModuleType::Dashboard => self.server_dashboard(&mut masses), ModuleType::Navigation => self.server_navigation(&mut masses), + ModuleType::Tractorbeam => self.server_tractorbeam(&mut masses), ModuleType::Construction => self.server_construction(&mut masses), } } diff --git a/src/server/mining.rs b/src/server/mining.rs index 6213e65..f6ddb41 100644 --- a/src/server/mining.rs +++ b/src/server/mining.rs @@ -5,7 +5,6 @@ use std::io::BufRead; use std::io::Write; use crate::mass::{Mass, MassType}; -use crate::math::distance; use crate::modules::mining::{Mining, MiningStatus}; use crate::modules::navigation::Navigation; use crate::server::connection::ServerConnection; @@ -52,7 +51,8 @@ impl ServerConnection { if let Some(item) = item { if !ship.give(item.clone()) { - let mass = Mass::new_item(item.clone(), ship.position, ship.velocity); + let mass = + Mass::new_item(item.clone(), ship.position.clone(), ship.velocity.clone()); masses.insert(item.name.clone(), mass); } } @@ -109,7 +109,9 @@ fn get_mining_data( let is_within_range = if has_astroid_target { match target { - Some(target) => mining.range > distance(ship.position, target.position), + Some(target) => { + mining.range > ship.position.distance_from(target.position.clone()) + } _ => false, } } else { diff --git a/src/server/mod.rs b/src/server/mod.rs index 0fec4dc..c195f3d 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -5,3 +5,4 @@ pub mod engines; pub mod mining; pub mod navigation; pub mod refinery; +pub mod tractorbeam; diff --git a/src/server/navigation.rs b/src/server/navigation.rs index eb9095d..5143667 100644 --- a/src/server/navigation.rs +++ b/src/server/navigation.rs @@ -5,7 +5,6 @@ use std::io::BufRead; use std::io::Write; use crate::mass::{Mass, MassType}; -use crate::math::distance; use crate::server::connection::ServerConnection; impl ServerConnection { @@ -18,11 +17,11 @@ impl ServerConnection { } = ship.mass_type { let navigation = navigation.as_mut().unwrap(); - navigation.verify_target(ship_clone.position, &masses); + navigation.verify_target(ship_clone.position.clone(), &masses); let mut within_range: HashMap<&String, &Mass> = masses .iter() .filter(|&(_, mass)| { - distance(ship_clone.position, mass.position) < navigation.range + ship_clone.position.distance_from(mass.position.clone()) < navigation.range }) .collect(); within_range.insert(&self.name, &ship_clone); diff --git a/src/server/tractorbeam.rs b/src/server/tractorbeam.rs new file mode 100644 index 0000000..250f5fb --- /dev/null +++ b/src/server/tractorbeam.rs @@ -0,0 +1,70 @@ +extern crate serde_json; + +use std::collections::HashMap; +use std::io::BufRead; +use std::io::Write; + +use crate::mass::{Mass, MassType}; +use crate::modules::navigation::NavigationStatus; +use crate::modules::tractorbeam::TractorbeamStatus; +use crate::server::connection::ServerConnection; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TractorbeamData { + pub has_target: bool, + pub status: TractorbeamStatus, +} + +impl ServerConnection { + pub fn server_tractorbeam(&mut self, masses: &mut HashMap) { + let mut ship = masses.remove(&self.name).unwrap(); + let ship_clone = ship.clone(); + + if let MassType::Ship { + ref mut tractorbeam, + ref navigation, + .. + } = ship.mass_type + { + let tractorbeam = tractorbeam.as_mut().unwrap(); + let navigation = navigation.as_ref().unwrap(); + + if self.open { + let tractorbeam_data = TractorbeamData { + has_target: navigation.status == NavigationStatus::Targeted, + status: tractorbeam.status.clone(), + }; + + let send = serde_json::to_string(&tractorbeam_data).unwrap() + "\n"; + self.open = match self.stream.write(send.as_bytes()) { + Ok(_result) => true, + Err(_error) => false, + }; + + let mut recv = String::new(); + if let Ok(result) = self.buff_r.read_line(&mut recv) { + match recv.as_bytes() { + b"o\n" => tractorbeam.toggle_pull(), + b"p\n" => tractorbeam.toggle_push(), + b"t\n" => tractorbeam.toggle_bring(5.0), + _ => { + if result == 0 { + self.open = false; + } + } + } + } + } + + if let Some(name) = navigation.target_name.clone() { + let target = masses.get_mut(&name).unwrap(); + let acceleration = tractorbeam.get_acceleration(ship_clone, target.clone()); + target.effects.give_acceleration(acceleration); + } else { + tractorbeam.off(); + } + } + + masses.insert(self.name.clone(), ship); + } +} -- cgit v1.2.3