Proper fix to the logout timeout problem using Disconnect ACK

This commit is contained in:
Capucho 2020-03-08 08:06:22 +00:00
parent d8ba63ffdc
commit 9d805a745e
5 changed files with 28 additions and 15 deletions

View File

@ -78,6 +78,8 @@ pub struct Client {
loaded_distance: f32,
pending_chunks: HashMap<Vec2<i32>, Instant>,
disconnected: bool,
}
impl Client {
@ -164,6 +166,8 @@ impl Client {
loaded_distance: 0.0,
pending_chunks: HashMap::new(),
disconnected: false,
})
}
@ -721,8 +725,9 @@ impl Client {
);
},
ServerMsg::Disconnect => {
self.disconnected = true;
frontend_events.push(Event::Disconnect);
self.client_state = ClientState::Disconnected;
self.postbox.send_message(ClientMsg::Terminate);
},
}
}
@ -735,6 +740,9 @@ impl Client {
Ok(frontend_events)
}
// Get's whether or not the client just disconnected
pub fn disconnected(&self) -> bool { self.disconnected }
/// Get the player's entity.
pub fn entity(&self) -> EcsEntity { self.entity }

View File

@ -35,4 +35,5 @@ pub enum ClientMsg {
key: Vec2<i32>,
},
Disconnect,
Terminate,
}

View File

@ -294,6 +294,9 @@ impl<'a> System<'a> for Sys {
ClientMsg::Disconnect => {
disconnect = true;
},
ClientMsg::Terminate => {
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
},
}
}
@ -308,7 +311,6 @@ impl<'a> System<'a> for Sys {
ServerMsg::broadcast(format!("{} went offline.", &player.alias)),
));
}
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
client.postbox.send_message(ServerMsg::Disconnect);
}
}

View File

@ -39,6 +39,11 @@ impl PlayState for CharSelectionState {
// Set up an fps clock.
let mut clock = Clock::start();
// Check if we just disconnected, if so go to main menu
if self.client.borrow().disconnected() {
return PlayStateResult::Pop;
}
let mut current_client_state = self.client.borrow().get_client_state();
while let ClientState::Pending | ClientState::Registered = current_client_state {
// Handle window events
@ -141,7 +146,7 @@ impl PlayState for CharSelectionState {
) {
global_state.info_message =
Some(localized_strings.get("common.connection_lost").to_owned());
error!("[session] Failed to tick the scene: {:?}", err);
error!("[char_selection] Failed to tick the scene: {:?}", err);
return PlayStateResult::Pop;
}

View File

@ -24,6 +24,14 @@ use specs::{Join, WorldExt};
use std::{cell::RefCell, rc::Rc, time::Duration};
use vek::*;
/// The action to perform after a tick
enum TickAction {
// Continue executing
Continue,
// Disconnected (i.e. go to main menu)
Disconnect,
}
pub struct SessionState {
scene: Scene,
client: Rc<RefCell<Client>>,
@ -33,14 +41,6 @@ pub struct SessionState {
selected_block: Block,
}
/// The action to perform after a tick
enum TickAction {
// Continue executing
Continue,
// Disconnected (i.e. go to main menu)
Disconnect,
}
/// Represents an active game session (i.e., the one being played).
impl SessionState {
/// Create a new `SessionState`.
@ -87,10 +87,7 @@ impl SessionState {
} => {
self.hud.new_message(event);
},
client::Event::Disconnect => {
log::warn!("disconnect");
return Ok(TickAction::Disconnect);
},
client::Event::Disconnect => return Ok(TickAction::Disconnect),
client::Event::DisconnectionNotification(time) => {
let message = match time {
0 => String::from("Goodbye!"),