diff --git a/client/src/lib.rs b/client/src/lib.rs index c0e2c45dae..5729b1857b 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -71,13 +71,10 @@ pub enum Event { SetViewDistance(u32), Outcome(Outcome), CharacterCreated(CharacterId), + CharacterError(String), } -pub struct Client { - registered: bool, - presence: Option, - thread_pool: ThreadPool, - pub server_info: ServerInfo, +pub struct WorldData { /// Just the "base" layer for LOD; currently includes colors and nothing /// else. In the future we'll add more layers, like shadows, rivers, and /// probably foliage, cities, roads, and other structures. @@ -99,9 +96,27 @@ pub struct Client { /// in chunks), and the third element holds the minimum height for any land /// chunk (i.e. the sea level) in its x coordinate, and the maximum land /// height above this height (i.e. the max height) in its y coordinate. - pub world_map: (Arc, Vec2, Vec2), - pub player_list: HashMap, - pub character_list: CharacterList, + map: (Arc, Vec2, Vec2), +} + +impl WorldData { + pub fn chunk_size(&self) -> Vec2 { self.map.1 } + + pub fn map_image(&self) -> &Arc { &self.map.0 } + + pub fn min_chunk_alt(&self) -> f32 { self.map.2.x } + + pub fn max_chunk_alt(&self) -> f32 { self.map.2.y } +} + +pub struct Client { + registered: bool, + presence: Option, + thread_pool: ThreadPool, + server_info: ServerInfo, + world_data: WorldData, + player_list: HashMap, + character_list: CharacterList, sites: Vec, recipe_book: RecipeBook, available_recipes: HashSet, @@ -146,7 +161,6 @@ pub struct Client { pub struct CharacterList { pub characters: Vec, pub loading: bool, - pub error: Option, } impl Client { @@ -385,10 +399,12 @@ impl Client { presence: None, thread_pool, server_info, - world_map, - lod_base, - lod_alt, - lod_horizon, + world_data: WorldData { + lod_base, + lod_alt, + lod_horizon, + map: world_map, + }, player_list: HashMap::new(), character_list: CharacterList::default(), sites, @@ -611,6 +627,14 @@ impl Client { } } + pub fn player_list(&self) -> &HashMap { &self.player_list } + + pub fn character_list(&self) -> &CharacterList { &self.character_list } + + pub fn server_info(&self) -> &ServerInfo { &self.server_info } + + pub fn world_data(&self) -> &WorldData { &self.world_data } + pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book } pub fn available_recipes(&self) -> &HashSet { &self.available_recipes } @@ -1480,13 +1504,13 @@ impl Client { }, ServerGeneral::CharacterActionError(error) => { warn!("CharacterActionError: {:?}.", error); - self.character_list.error = Some(error); + events.push(Event::CharacterError(error)); }, ServerGeneral::CharacterDataLoadError(error) => { trace!("Handling join error by server"); self.presence = None; self.clean_state(); - self.character_list.error = Some(error); + events.push(Event::CharacterError(error)); }, ServerGeneral::CharacterCreated(character_id) => { events.push(Event::CharacterCreated(character_id)); diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 7cc7b279ca..57ee603e79 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -178,7 +178,7 @@ impl<'a> Widget for Group<'a> { } // Helper - let uid_to_name_text = |uid, client: &Client| match client.player_list.get(&uid) { + let uid_to_name_text = |uid, client: &Client| match client.player_list().get(&uid) { Some(player_info) => player_info .character .as_ref() diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index c6a1452f97..1da67e06f1 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -648,10 +648,10 @@ impl Hud { // Load world map let world_map = ( ui.add_graphic_with_rotations(Graphic::Image( - Arc::clone(&client.world_map.0), + Arc::clone(client.world_data().map_image()), Some(water_color), )), - client.world_map.1.map(u32::from), + client.world_data().chunk_size().map(|e| e as u32), ); // Load images. let imgs = Imgs::load(&mut ui).expect("Failed to load images!"); @@ -666,7 +666,7 @@ impl Hud { // Load fonts. let fonts = Fonts::load(&i18n.fonts, &mut ui).expect("Impossible to load fonts!"); // Get the server name. - let server = &client.server_info.name; + let server = &client.server_info().name; // Get the id, unwrap is safe because this CANNOT be None at this // point. diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index 20e7641373..1a5423a330 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -266,7 +266,11 @@ impl<'a> Widget for Social<'a> { } // Online Tab if let SocialTab::Online = self.show.social_tab { - let players = self.client.player_list.iter().filter(|(_, p)| p.is_online); + let players = self + .client + .player_list() + .iter() + .filter(|(_, p)| p.is_online); let count = players.clone().count(); let height = if count > 1 { count as f64 - 1.0 + 20.0 * count as f64 - 1.0 @@ -517,12 +521,12 @@ impl<'a> Widget for Social<'a> { .as_ref() .map(|(s, _)| *s) .filter(|selected| { - self.client - .player_list - .get(selected) - .map_or(false, |selected_player| { + self.client.player_list().get(selected).map_or( + false, + |selected_player| { selected_player.is_online && selected_player.character.is_some() - }) + }, + ) }) .or_else(|| { self.selected_entity diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 8458e235ea..592d3fc07f 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -44,7 +44,7 @@ impl CharSelectionState { client: &'a Client, ) -> (Option, Option<&'a comp::Loadout>) { char_selection_ui - .display_body_loadout(&client.character_list.characters) + .display_body_loadout(&client.character_list().characters) .map(|(body, loadout)| { ( match body { @@ -124,11 +124,11 @@ impl PlayState for CharSelectionState { ))); }, ui::Event::ClearCharacterListError => { - self.client.borrow_mut().character_list.error = None; + self.char_selection_ui.error = None; }, ui::Event::SelectCharacter(selected) => { let client = self.client.borrow(); - let server_name = &client.server_info.name; + let server_name = &client.server_info().name; // Select newly created character global_state .profile @@ -194,6 +194,9 @@ impl PlayState for CharSelectionState { client::Event::CharacterCreated(character_id) => { self.char_selection_ui.select_character(character_id); }, + client::Event::CharacterError(error) => { + self.char_selection_ui.display_error(error); + }, _ => {}, } } diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 614d0cc9b1..b484bd2995 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -287,7 +287,12 @@ impl Controls { } } - fn view(&mut self, _settings: &Settings, client: &Client) -> Element { + fn view( + &mut self, + _settings: &Settings, + client: &Client, + error: &Option, + ) -> Element { // TODO: use font scale thing for text size (use on button size for buttons with // text) @@ -348,7 +353,7 @@ impl Controls { // Note: we don't need to persist this because it is the default if self.selected.is_none() { self.selected = client - .character_list + .character_list() .characters .get(0) .and_then(|i| i.character.id); @@ -356,13 +361,13 @@ impl Controls { // Get the index of the selected character let selected = self.selected.and_then(|id| { client - .character_list + .character_list() .characters .iter() .position(|i| i.character.id == Some(id)) }); - if let Some(error) = &client.character_list.error { + if let Some(error) = error { // TODO: use more user friendly errors with suggestions on potential solutions // instead of directly showing error message here *info_content = Some(InfoContent::CharacterError(format!( @@ -377,14 +382,14 @@ impl Controls { Some(InfoContent::LoadingCharacters) | Some(InfoContent::CreatingCharacter) | Some(InfoContent::DeletingCharacter) - ) && !client.character_list.loading + ) && !client.character_list().loading { *info_content = None; } let server = Container::new( Column::with_children(vec![ - Text::new(&client.server_info.name) + Text::new(&client.server_info().name) .size(fonts.cyri.scale(25)) .into(), // TODO: show additional server info here @@ -399,7 +404,7 @@ impl Controls { .width(Length::Fill); let characters = { - let characters = &client.character_list.characters; + let characters = &client.character_list().characters; let num = characters.len(); // Ensure we have enough button states character_buttons.resize_with(num * 2, Default::default); @@ -1387,12 +1392,13 @@ pub struct CharSelectionUi { controls: Controls, enter_pressed: bool, select_character: Option, + pub error: Option, } impl CharSelectionUi { pub fn new(global_state: &mut GlobalState, client: &Client) -> Self { // Load up the last selected character for this server - let server_name = &client.server_info.name; + let server_name = &client.server_info().name; let selected_character = global_state.profile.get_selected_character(server_name); // Load language @@ -1432,6 +1438,7 @@ impl CharSelectionUi { controls, enter_pressed: false, select_character: None, + error: None, } } @@ -1491,12 +1498,15 @@ impl CharSelectionUi { pub fn select_character(&mut self, id: CharacterId) { self.select_character = Some(id); } + pub fn display_error(&mut self, error: String) { self.error = Some(error); } + // TODO: do we need whole client here or just character list? pub fn maintain(&mut self, global_state: &mut GlobalState, client: &Client) -> Vec { let mut events = Vec::new(); let (mut messages, _) = self.ui.maintain( - self.controls.view(&global_state.settings, &client), + self.controls + .view(&global_state.settings, &client, &self.error), global_state.window.renderer_mut(), global_state.clipboard.as_ref(), ); @@ -1514,7 +1524,7 @@ impl CharSelectionUi { self.controls.update( message, &mut events, - &client.character_list.characters, + &client.character_list().characters, &*client.state().ability_map(), ) }); diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index fdfbf17782..76dab1b870 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -28,10 +28,10 @@ impl Lod { locals: renderer.create_consts(&[Locals::default()]).unwrap(), data: LodData::new( renderer, - client.world_map.1, - &client.lod_base.raw(), - &client.lod_alt.raw(), - &client.lod_horizon.raw(), + client.world_data().chunk_size(), + client.world_data().lod_base.raw(), + client.world_data().lod_alt.raw(), + client.world_data().lod_horizon.raw(), settings.graphics.lod_detail.max(100).min(2500), water_color().into_array().into(), ), diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 8c6d551ee7..fb9a9e4769 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -304,7 +304,10 @@ impl Scene { terrain: Terrain::new(renderer), lod: Lod::new(renderer, client, settings), loaded_distance: 0.0, - map_bounds: client.world_map.2, + map_bounds: Vec2::new( + client.world_data().min_chunk_alt(), + client.world_data().max_chunk_alt(), + ), select_pos: None, light_data: Vec::new(), particle_mgr: ParticleMgr::new(renderer), diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index e1783f237c..a4825c36a3 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -106,7 +106,10 @@ impl Scene { let start_angle = 90.0f32.to_radians(); let resolution = renderer.get_resolution().map(|e| e as f32); - let map_bounds = client.world_map.2; + let map_bounds = Vec2::new( + client.world_data().min_chunk_alt(), + client.world_data().max_chunk_alt(), + ); let map_border = [0.0, 0.0, 0.0, 0.0]; let map_image = [0]; let alt_image = [0]; diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 3c7002c475..ad20824894 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -183,6 +183,7 @@ impl SessionState { }, client::Event::Outcome(outcome) => outcomes.push(outcome), client::Event::CharacterCreated(_) => {}, + client::Event::CharacterError(_) => {}, } } @@ -931,7 +932,7 @@ impl PlayState for SessionState { HudEvent::ChangeHotbarState(state) => { let client = self.client.borrow(); - let server_name = &client.server_info.name; + let server_name = &client.server_info().name; // If we are changing the hotbar state this CANNOT be None. let character_id = match client.presence().unwrap() { PresenceKind::Character(id) => id,