mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Wait for ingame pipelines to build before entering char select, show pipeline rebuilding status text in the graphics settings tab
This commit is contained in:
parent
9c3e3ea638
commit
30f02af6a4
@ -35,6 +35,7 @@ widget_ids! {
|
||||
window_scrollbar,
|
||||
reset_graphics_button,
|
||||
fps_counter,
|
||||
pipeline_recreation_text,
|
||||
vd_slider,
|
||||
vd_text,
|
||||
vd_value,
|
||||
@ -210,6 +211,24 @@ impl<'a> Widget for Video<'a> {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.set(state.ids.fps_counter, ui);
|
||||
|
||||
// Pipeline recreation status
|
||||
if let Some((total, complete)) = self
|
||||
.global_state
|
||||
.window
|
||||
.renderer()
|
||||
.pipeline_recreation_status()
|
||||
{
|
||||
Text::new(&format!("Rebuilding pipelines: ({}/{})", complete, total))
|
||||
.down_from(state.ids.fps_counter, 10.0)
|
||||
.align_right_of(state.ids.fps_counter)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
// TODO: make color pulse or something
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.pipeline_recreation_text, ui);
|
||||
}
|
||||
|
||||
// View Distance
|
||||
Text::new(&self.localized_strings.get("hud.settings.view_distance"))
|
||||
.top_left_with_margins_on(state.ids.window, 10.0, 10.0)
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
use client::{
|
||||
addr::ConnectionArgs,
|
||||
error::{InitProtocolError, NetworkConnectError, NetworkError},
|
||||
ServerInfo,
|
||||
Client, ServerInfo,
|
||||
};
|
||||
use client_init::{ClientInit, Error as InitError, Msg as InitMsg};
|
||||
use common::comp;
|
||||
@ -23,10 +23,29 @@ use tokio::runtime;
|
||||
use tracing::error;
|
||||
use ui::{Event as MainMenuEvent, MainMenuUi};
|
||||
|
||||
// TODO: show status messages for waiting on server creation, client init, and
|
||||
// pipeline creation (we can show progress of pipeline creation)
|
||||
enum InitState {
|
||||
None,
|
||||
// Waiting on the client initialization
|
||||
Client(ClientInit),
|
||||
// Client initialized but still waiting on Renderer pipeline creation
|
||||
Pipeline(Client),
|
||||
}
|
||||
|
||||
impl InitState {
|
||||
fn client(&self) -> Option<&ClientInit> {
|
||||
if let Self::Client(client_init) = &self {
|
||||
Some(client_init)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MainMenuState {
|
||||
main_menu_ui: MainMenuUi,
|
||||
// Used for client creation.
|
||||
client_init: Option<ClientInit>,
|
||||
init: InitState,
|
||||
scene: Scene,
|
||||
}
|
||||
|
||||
@ -35,7 +54,7 @@ impl MainMenuState {
|
||||
pub fn new(global_state: &mut GlobalState) -> Self {
|
||||
Self {
|
||||
main_menu_ui: MainMenuUi::new(global_state),
|
||||
client_init: None,
|
||||
init: InitState::None,
|
||||
scene: Scene::new(global_state.window.renderer_mut()),
|
||||
}
|
||||
}
|
||||
@ -78,14 +97,14 @@ impl PlayState for MainMenuState {
|
||||
"singleplayer".to_owned(),
|
||||
"".to_owned(),
|
||||
ConnectionArgs::Mpsc(14004),
|
||||
&mut self.client_init,
|
||||
&mut self.init,
|
||||
Some(runtime),
|
||||
);
|
||||
},
|
||||
Ok(Err(e)) => {
|
||||
error!(?e, "Could not start server");
|
||||
global_state.singleplayer = None;
|
||||
self.client_init = None;
|
||||
self.init = InitState::None;
|
||||
self.main_menu_ui.cancel_connection();
|
||||
self.main_menu_ui.show_info(format!("Error: {:?}", e));
|
||||
},
|
||||
@ -108,19 +127,14 @@ impl PlayState for MainMenuState {
|
||||
}
|
||||
}
|
||||
// Poll client creation.
|
||||
match self.client_init.as_ref().and_then(|init| init.poll()) {
|
||||
match self.init.client().and_then(|init| init.poll()) {
|
||||
Some(InitMsg::Done(Ok(mut client))) => {
|
||||
self.client_init = None;
|
||||
self.main_menu_ui.connected();
|
||||
// Register voxygen components / resources
|
||||
crate::ecs::init(client.state_mut().ecs_mut());
|
||||
return PlayStateResult::Push(Box::new(CharSelectionState::new(
|
||||
global_state,
|
||||
std::rc::Rc::new(std::cell::RefCell::new(client)),
|
||||
)));
|
||||
self.init = InitState::Pipeline(client);
|
||||
},
|
||||
Some(InitMsg::Done(Err(e))) => {
|
||||
self.client_init = None;
|
||||
self.init = InitState::None;
|
||||
tracing::trace!(?e, "raw Client Init error");
|
||||
let e = get_client_msg_error(e, &global_state.i18n);
|
||||
// Log error for possible additional use later or incase that the error
|
||||
@ -136,10 +150,7 @@ impl PlayState for MainMenuState {
|
||||
.contains(&auth_server)
|
||||
{
|
||||
// Can't fail since we just polled it, it must be Some
|
||||
self.client_init
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.auth_trust(auth_server, true);
|
||||
self.init.client().unwrap().auth_trust(auth_server, true);
|
||||
} else {
|
||||
// Show warning that auth server is not trusted and prompt for approval
|
||||
self.main_menu_ui.auth_trust_prompt(auth_server);
|
||||
@ -148,6 +159,64 @@ impl PlayState for MainMenuState {
|
||||
None => {},
|
||||
}
|
||||
|
||||
// Tick the client to keep the connection alive if we are waiting on pipelines
|
||||
let localized_strings = &global_state.i18n.read();
|
||||
if let InitState::Pipeline(client) = &mut self.init {
|
||||
match client.tick(
|
||||
comp::ControllerInputs::default(),
|
||||
global_state.clock.dt(),
|
||||
|_| {},
|
||||
) {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
match event {
|
||||
client::Event::SetViewDistance(vd) => {
|
||||
global_state.settings.graphics.view_distance = vd;
|
||||
global_state.settings.save_to_file_warn();
|
||||
},
|
||||
client::Event::Disconnect => {
|
||||
global_state.info_message = Some(
|
||||
localized_strings
|
||||
.get("main.login.server_shut_down")
|
||||
.to_owned(),
|
||||
);
|
||||
self.init = InitState::None;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
global_state.info_message =
|
||||
Some(localized_strings.get("common.connection_lost").to_owned());
|
||||
error!(?err, "[main menu] Failed to tick the client");
|
||||
self.init = InitState::None;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Poll renderer pipeline creation
|
||||
if let InitState::Pipeline(..) = &self.init {
|
||||
// If not complete go to char select screen
|
||||
if global_state
|
||||
.window
|
||||
.renderer()
|
||||
.pipeline_creation_status()
|
||||
.is_none()
|
||||
{
|
||||
// Always succeeds since we check above
|
||||
if let InitState::Pipeline(client) =
|
||||
core::mem::replace(&mut self.init, InitState::None)
|
||||
{
|
||||
self.main_menu_ui.connected();
|
||||
return PlayStateResult::Push(Box::new(CharSelectionState::new(
|
||||
global_state,
|
||||
std::rc::Rc::new(std::cell::RefCell::new(client)),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maintain the UI.
|
||||
for event in self
|
||||
.main_menu_ui
|
||||
@ -184,19 +253,19 @@ impl PlayState for MainMenuState {
|
||||
username,
|
||||
password,
|
||||
connection_args,
|
||||
&mut self.client_init,
|
||||
&mut self.init,
|
||||
None,
|
||||
);
|
||||
},
|
||||
MainMenuEvent::CancelLoginAttempt => {
|
||||
// client_init contains Some(ClientInit), which spawns a thread which contains a
|
||||
// TcpStream::connect() call This call is blocking
|
||||
// TODO fix when the network rework happens
|
||||
// init contains InitState::Client(ClientInit), which spawns a thread which
|
||||
// contains a TcpStream::connect() call This call is
|
||||
// blocking TODO fix when the network rework happens
|
||||
#[cfg(feature = "singleplayer")]
|
||||
{
|
||||
global_state.singleplayer = None;
|
||||
}
|
||||
self.client_init = None;
|
||||
self.init = InitState::None;
|
||||
self.main_menu_ui.cancel_connection();
|
||||
},
|
||||
MainMenuEvent::ChangeLanguage(new_language) => {
|
||||
@ -232,8 +301,8 @@ impl PlayState for MainMenuState {
|
||||
.insert(auth_server.clone());
|
||||
global_state.settings.save_to_file_warn();
|
||||
}
|
||||
self.client_init
|
||||
.as_ref()
|
||||
self.init
|
||||
.client()
|
||||
.map(|init| init.auth_trust(auth_server, trust));
|
||||
},
|
||||
}
|
||||
@ -369,7 +438,7 @@ fn attempt_login(
|
||||
username: String,
|
||||
password: String,
|
||||
connection_args: ConnectionArgs,
|
||||
client_init: &mut Option<ClientInit>,
|
||||
init: &mut InitState,
|
||||
runtime: Option<Arc<runtime::Runtime>>,
|
||||
) {
|
||||
if let Err(err) = comp::Player::alias_validate(&username) {
|
||||
@ -378,8 +447,8 @@ fn attempt_login(
|
||||
}
|
||||
|
||||
// Don't try to connect if there is already a connection in progress.
|
||||
if client_init.is_none() {
|
||||
*client_init = Some(ClientInit::new(
|
||||
if let InitState::None = init {
|
||||
*init = InitState::Client(ClientInit::new(
|
||||
connection_args,
|
||||
username,
|
||||
password,
|
||||
|
@ -388,6 +388,28 @@ impl Renderer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Check the status of the intial pipeline creation
|
||||
/// Returns `None` if complete
|
||||
/// Returns `Some((total, complete))` if in progress
|
||||
pub fn pipeline_creation_status(&self) -> Option<(usize, usize)> {
|
||||
if let State::Interface { creating, .. } = &self.state {
|
||||
Some(creating.status())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the status the pipeline recreation
|
||||
/// Returns `None` if pipelines are currently not being recreated
|
||||
/// Returns `Some((total, complete))` if in progress
|
||||
pub fn pipeline_recreation_status(&self) -> Option<(usize, usize)> {
|
||||
if let State::Complete { recreating, .. } = &self.state {
|
||||
recreating.as_ref().map(|r| r.status())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the render mode.
|
||||
pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> {
|
||||
// TODO: are there actually any issues with the current mode not matching the
|
||||
|
Loading…
Reference in New Issue
Block a user