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 d131a5ce8f
commit cc5845d756
5 changed files with 28 additions and 15 deletions

View File

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

View File

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

View File

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

View File

@ -39,6 +39,11 @@ impl PlayState for CharSelectionState {
// Set up an fps clock. // Set up an fps clock.
let mut clock = Clock::start(); 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(); let mut current_client_state = self.client.borrow().get_client_state();
while let ClientState::Pending | ClientState::Registered = current_client_state { while let ClientState::Pending | ClientState::Registered = current_client_state {
// Handle window events // Handle window events
@ -141,7 +146,7 @@ impl PlayState for CharSelectionState {
) { ) {
global_state.info_message = global_state.info_message =
Some(localized_strings.get("common.connection_lost").to_owned()); 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; return PlayStateResult::Pop;
} }

View File

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