Removed public fields from Client, turned a character error into a frontend event

This commit is contained in:
Joshua Barretto 2020-11-25 17:13:59 +00:00
parent e413392694
commit 77a39d74d4
10 changed files with 93 additions and 45 deletions

View File

@ -71,13 +71,10 @@ pub enum Event {
SetViewDistance(u32),
Outcome(Outcome),
CharacterCreated(CharacterId),
CharacterError(String),
}
pub struct Client {
registered: bool,
presence: Option<PresenceKind>,
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<DynamicImage>, Vec2<u16>, Vec2<f32>),
pub player_list: HashMap<Uid, PlayerInfo>,
pub character_list: CharacterList,
map: (Arc<DynamicImage>, Vec2<u16>, Vec2<f32>),
}
impl WorldData {
pub fn chunk_size(&self) -> Vec2<u16> { self.map.1 }
pub fn map_image(&self) -> &Arc<DynamicImage> { &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<PresenceKind>,
thread_pool: ThreadPool,
server_info: ServerInfo,
world_data: WorldData,
player_list: HashMap<Uid, PlayerInfo>,
character_list: CharacterList,
sites: Vec<SiteInfo>,
recipe_book: RecipeBook,
available_recipes: HashSet<String>,
@ -146,7 +161,6 @@ pub struct Client {
pub struct CharacterList {
pub characters: Vec<CharacterItem>,
pub loading: bool,
pub error: Option<String>,
}
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<Uid, PlayerInfo> { &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<String> { &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));

View File

@ -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()

View File

@ -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.

View File

@ -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

View File

@ -44,7 +44,7 @@ impl CharSelectionState {
client: &'a Client,
) -> (Option<comp::humanoid::Body>, 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);
},
_ => {},
}
}

View File

@ -287,7 +287,12 @@ impl Controls {
}
}
fn view(&mut self, _settings: &Settings, client: &Client) -> Element<Message> {
fn view(
&mut self,
_settings: &Settings,
client: &Client,
error: &Option<String>,
) -> Element<Message> {
// 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<CharacterId>,
pub error: Option<String>,
}
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<Event> {
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(),
)
});

View File

@ -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(),
),

View File

@ -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),

View File

@ -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];

View File

@ -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,