From 529b655cf95b31be8ce42164e9ef6d9d5bc87745 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 19 May 2019 01:45:02 +0100 Subject: [PATCH] Added view distance configuration Former-commit-id: b3c7a21631ce0c6b058f25aede0e3e2895a16f81 --- .gitignore | 1 + client/src/lib.rs | 18 +++++++++----- common/src/comp/player.rs | 8 ++++-- common/src/msg/client.rs | 1 + server/src/cmd.rs | 11 ++++++--- server/src/lib.rs | 27 +++++++++++++++------ voxygen/src/hud/mod.rs | 10 ++++---- voxygen/src/hud/settings_window.rs | 8 +++--- voxygen/src/menu/main/client_init.rs | 9 ++----- voxygen/src/menu/main/mod.rs | 2 +- voxygen/src/menu/main/start_singleplayer.rs | 2 +- voxygen/src/session.rs | 5 ++-- voxygen/src/window.rs | 2 ++ 13 files changed, 65 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index abc6feeddb..c876600634 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ # Veloren voxygen/keybinds.toml settings.toml +voxygen/settings/ *.rar *.log run.sh diff --git a/client/src/lib.rs b/client/src/lib.rs index d1e4d1508a..b2ea500e61 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -44,7 +44,7 @@ pub struct Client { tick: u64, state: State, entity: EcsEntity, - view_distance: u64, + view_distance: Option, pending_chunks: HashMap, Instant>, } @@ -52,7 +52,7 @@ pub struct Client { impl Client { /// Create a new `Client`. #[allow(dead_code)] - pub fn new>(addr: A, view_distance: u64) -> Result { + pub fn new>(addr: A, view_distance: Option) -> Result { let mut client_state = Some(ClientState::Connected); let mut postbox = PostBox::to(addr)?; @@ -94,6 +94,12 @@ impl Client { self.postbox.send_message(ClientMsg::Register { player }); } + pub fn set_view_distance(&mut self, view_distance: u32) { + self.view_distance = Some(view_distance.max(5).min(25)); + self.postbox + .send_message(ClientMsg::SetViewDistance(self.view_distance.unwrap())); // Can't fail + } + /// Get a reference to the client's worker thread pool. This pool should be used for any /// computationally expensive operations that run outside of the main thread (i.e., threads that /// block on I/O operations are exempt). @@ -198,16 +204,16 @@ impl Client { .read_storage::() .get(self.entity) .cloned(); - if let Some(pos) = pos { + if let (Some(pos), Some(view_distance)) = (pos, self.view_distance) { let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); // Remove chunks that are too far from the player. let mut chunks_to_remove = Vec::new(); self.state.terrain().iter().for_each(|(key, _)| { if (Vec2::from(chunk_pos) - Vec2::from(key)) - .map(|e: i32| e.abs()) + .map(|e: i32| e.abs() as u32) .reduce_max() - > 10 + > view_distance { chunks_to_remove.push(key); } @@ -218,7 +224,7 @@ impl Client { // Request chunks from the server. // TODO: This is really inefficient. - 'outer: for dist in 0..10 { + 'outer: for dist in 0..view_distance as i32 { for i in chunk_pos.x - dist..chunk_pos.x + dist + 1 { for j in chunk_pos.y - dist..chunk_pos.y + dist + 1 { let key = Vec2::new(i, j); diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index 6f3bc54ef0..2c895083e0 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -3,11 +3,15 @@ use specs::{Component, FlaggedStorage, VecStorage}; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Player { pub alias: String, + pub view_distance: Option, } impl Player { - pub fn new(alias: String) -> Self { - Self { alias } + pub fn new(alias: String, view_distance: Option) -> Self { + Self { + alias, + view_distance, + } } } diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 80756d9d94..2c3d2bbc3f 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -12,6 +12,7 @@ pub enum ClientMsg { body: comp::Body, }, RequestState(ClientState), + SetViewDistance(u32), Ping, Pong, Chat(String), diff --git a/server/src/cmd.rs b/server/src/cmd.rs index c0b3df6776..b31ed2ee28 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -135,9 +135,14 @@ fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &Ch fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { let opt_alias = scan_fmt!(&args, action.arg_fmt, String); match opt_alias { - Some(alias) => server - .state - .write_component(entity, comp::player::Player { alias }), + Some(alias) => { + server + .state + .ecs_mut() + .write_storage::() + .get_mut(entity) + .map(|player| player.alias = alias); + } None => server .clients .notify(entity, ServerMsg::Chat(String::from(action.help_string))), diff --git a/server/src/lib.rs b/server/src/lib.rs index 8a818e6b2f..e1e94d1e86 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -198,9 +198,9 @@ impl Server { let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); let dist = (Vec2::from(chunk_pos) - Vec2::from(key)) .map(|e: i32| e.abs()) - .reduce_max(); + .reduce_max() as u32; - if dist < 10 { + if player.view_distance.map(|vd| dist < vd).unwrap_or(false) { self.clients.notify( entity, ServerMsg::TerrainChunkUpdate { @@ -218,10 +218,10 @@ impl Server { // Remove chunks that are too far from players. let mut chunks_to_remove = Vec::new(); self.state.terrain().iter().for_each(|(key, _)| { - let mut min_dist = i32::MAX; + let mut should_drop = true; // For each player with a position, calculate the distance. - for (_, pos) in ( + for (player, pos) in ( &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), ) @@ -229,12 +229,15 @@ impl Server { { let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); let dist = Vec2::from(chunk_pos - key) - .map(|e: i32| e.abs()) + .map(|e: i32| e.abs() as u32) .reduce_max(); - min_dist = min_dist.min(dist); + + if player.view_distance.map(|vd| dist <= vd).unwrap_or(false) { + should_drop = false; + } } - if min_dist > 10 { + if should_drop { chunks_to_remove.push(key); } }); @@ -340,6 +343,16 @@ impl Server { // Use RequestState instead (No need to send `player` again). _ => client.error_state(RequestStateError::Impossible), }, + ClientMsg::SetViewDistance(view_distance) => match client.client_state { + ClientState::Character { .. } => { + state + .ecs_mut() + .write_storage::() + .get_mut(entity) + .map(|player| player.view_distance = Some(view_distance)); + } + _ => {} + }, ClientMsg::Character { name, body } => match client.client_state { // Become Registered first. ClientState::Connected => { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index acad613cca..1a7fabc077 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -90,7 +90,7 @@ font_ids! { pub enum Event { SendMessage(String), - AdjustVd(u8), + AdjustViewDistance(u32), Logout, Quit, } @@ -209,7 +209,7 @@ pub struct Hud { settings: Settings, force_ungrab: bool, // TODO: move to settings - current_vd: u8, + current_vd: u32, } impl Hud { @@ -386,9 +386,9 @@ impl Hud { } settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug, settings_window::Event::Close => self.show.open_windows = Windows::None, - settings_window::Event::AdjustVd(new_vd) => { - self.current_vd = new_vd; - events.push(Event::AdjustVd(new_vd)); + settings_window::Event::AdjustViewDistance(view_distance) => { + self.current_vd = view_distance; + events.push(Event::AdjustViewDistance(view_distance)); } } } diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index 11573b8d63..3f340ebe4b 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -62,14 +62,14 @@ pub struct SettingsWindow<'a> { imgs: &'a Imgs, fonts: &'a Fonts, - current_vd: u8, + current_vd: u32, #[conrod(common_builder)] common: widget::CommonBuilder, } impl<'a> SettingsWindow<'a> { - pub fn new(show: &'a Show, imgs: &'a Imgs, fonts: &'a Fonts, current_vd: u8) -> Self { + pub fn new(show: &'a Show, imgs: &'a Imgs, fonts: &'a Fonts, current_vd: u32) -> Self { Self { show, imgs, @@ -91,7 +91,7 @@ pub enum Event { ToggleInventoryTestButton, ToggleDebug, Close, - AdjustVd(u8), + AdjustViewDistance(u32), } impl<'a> Widget for SettingsWindow<'a> { @@ -489,7 +489,7 @@ impl<'a> Widget for SettingsWindow<'a> { .pad_track((5.0, 5.0)) .set(state.ids.vd_slider, ui) { - events.push(Event::AdjustVd(new_val)); + events.push(Event::AdjustViewDistance(new_val as u32)); } } // 5 Sound diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 933db4b8a4..ceef63c874 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -24,13 +24,8 @@ pub struct ClientInit { rx: Receiver>, } impl ClientInit { - pub fn new( - connection_args: (String, u16, bool), - client_args: (comp::Player, u64), - wait: bool, - ) -> Self { + pub fn new(connection_args: (String, u16, bool), player: comp::Player, wait: bool) -> Self { let (server_address, default_port, prefer_ipv6) = connection_args; - let (player, view_distance) = client_args; let (tx, rx) = channel(); @@ -53,7 +48,7 @@ impl ClientInit { let mut last_err = None; for socket_addr in first_addrs.into_iter().chain(second_addrs) { - match Client::new(socket_addr, view_distance) { + match Client::new(socket_addr, player.view_distance) { Ok(mut client) => { client.register(player); let _ = tx.send(Ok(client)); diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 2cdd432e7b..f59e06f4a3 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -106,7 +106,7 @@ impl PlayState for MainMenuState { // Don't try to connect if there is already a connection in progress. client_init = client_init.or(Some(ClientInit::new( (server_address, DEFAULT_PORT, false), - (comp::Player::new(username.clone()), 300), + comp::Player::new(username.clone(), Some(10)), false, ))); } diff --git a/voxygen/src/menu/main/start_singleplayer.rs b/voxygen/src/menu/main/start_singleplayer.rs index 87d3220bfd..addd4be521 100644 --- a/voxygen/src/menu/main/start_singleplayer.rs +++ b/voxygen/src/menu/main/start_singleplayer.rs @@ -30,7 +30,7 @@ impl PlayState for StartSingleplayerState { let client_init = ClientInit::new( (server_address.clone(), self.sock.port(), false), - (comp::Player::new(username.clone()), 300), + comp::Player::new(username.clone(), Some(10)), true, ); diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 912adfc7b3..6f7993be2b 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -190,9 +190,8 @@ impl PlayState for SessionState { HudEvent::Quit => { return PlayStateResult::Shutdown; } - HudEvent::AdjustVd(new_vd) => { - println!("New VD is {}, TODO: Actually change VD", new_vd); - //self.client.borrow_mut().set_vd(new_vd); + HudEvent::AdjustViewDistance(view_distance) => { + self.client.borrow_mut().set_view_distance(view_distance) } } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index d91c7d8bdc..9b8357afcc 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -216,6 +216,8 @@ pub enum Event { KeyUp(Key), /// Event that the ui uses. Ui(ui::Event), + // The view distance has been changed + ViewDistanceChanged(u32), /// Game settings have changed. SettingsChanged, }