Implement the Player Timeout as config

This commit is contained in:
Marcel Märtens 2020-09-06 21:24:52 +02:00
parent 198c12babc
commit 961b8a4d7c
5 changed files with 22 additions and 16 deletions

View File

@ -52,14 +52,6 @@ use tracing::{debug, error, trace, warn};
use uvth::{ThreadPool, ThreadPoolBuilder};
use vek::*;
// The duration of network inactivity until the player is kicked
// @TODO: in the future, this should be configurable on the server
// and be provided to the client
const SERVER_TIMEOUT: f64 = 40.0;
// After this duration has elapsed, the user will begin getting kick warnings in
// their chat window
const SERVER_TIMEOUT_GRACE_PERIOD: f64 = 14.0;
const PING_ROLLING_AVERAGE_SECS: usize = 10;
pub enum Event {
@ -117,6 +109,7 @@ pub struct Client {
participant: Option<Participant>,
singleton_stream: Stream,
client_timeout: Duration,
last_server_ping: f64,
last_server_pong: f64,
last_ping_delta: f64,
@ -173,6 +166,7 @@ impl Client {
world_map,
recipe_book,
max_group_size,
client_timeout,
) = block_on(async {
loop {
match stream.recv().await? {
@ -181,6 +175,7 @@ impl Client {
server_info,
time_of_day,
max_group_size,
client_timeout,
world_map,
recipe_book,
} => {
@ -358,6 +353,7 @@ impl Client {
(world_map, map_size, map_bounds),
recipe_book,
max_group_size,
client_timeout,
));
},
ServerMsg::TooManyPlayers => break Err(Error::TooManyPlayers),
@ -399,6 +395,7 @@ impl Client {
_network: network,
participant: Some(participant),
singleton_stream: stream,
client_timeout,
last_server_ping: 0.0,
last_server_pong: 0.0,
@ -1434,7 +1431,10 @@ impl Client {
let duration_since_last_pong = self.state.get_time() - self.last_server_pong;
// Dispatch a notification to the HUD warning they will be kicked in {n} seconds
if duration_since_last_pong >= SERVER_TIMEOUT_GRACE_PERIOD
const KICK_WARNING_AFTER_REL_TO_TIMEOUT_FRACTION: f64 = 0.75;
if duration_since_last_pong
>= (self.client_timeout.as_secs() as f64
* KICK_WARNING_AFTER_REL_TO_TIMEOUT_FRACTION)
&& self.state.get_time() - duration_since_last_pong > 0.
{
frontend_events.push(Event::DisconnectionNotification(
@ -1453,7 +1453,9 @@ impl Client {
)
})?;
if handles_msg == 0 && self.state.get_time() - self.last_server_pong > SERVER_TIMEOUT {
if handles_msg == 0
&& self.state.get_time() - self.last_server_pong > self.client_timeout.as_secs() as f64
{
return Err(Error::ServerTimeout);
}

View File

@ -11,6 +11,7 @@ use crate::{
use authc::AuthClientError;
use hashbrown::HashMap;
use serde::{Deserialize, Serialize};
use std::time::Duration;
use vek::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -189,6 +190,7 @@ pub enum ServerMsg {
server_info: ServerInfo,
time_of_day: state::TimeOfDay,
max_group_size: u32,
client_timeout: Duration,
world_map: WorldMapMsg,
recipe_book: RecipeBook,
},

View File

@ -70,8 +70,6 @@ use world::{
#[macro_use] extern crate diesel;
#[macro_use] extern crate diesel_migrations;
const CLIENT_TIMEOUT: f64 = 40.0; // Seconds
#[derive(Copy, Clone)]
struct SpawnPoint(Vec3<f32>);
@ -753,6 +751,7 @@ impl Server {
server_info: self.get_server_info(),
time_of_day: *self.state.ecs().read_resource(),
max_group_size: self.settings().max_player_group_size,
client_timeout: self.settings().client_timeout,
world_map: self.map.clone(),
recipe_book: (&*default_recipe_book()).clone(),
});

View File

@ -1,6 +1,6 @@
use portpicker::pick_unused_port;
use serde::{Deserialize, Serialize};
use std::{fs, io::prelude::*, net::SocketAddr, path::PathBuf};
use std::{fs, io::prelude::*, net::SocketAddr, path::PathBuf, time::Duration};
use tracing::{error, warn};
use world::sim::FileOpts;
@ -27,6 +27,7 @@ pub struct ServerSettings {
pub max_view_distance: Option<u32>,
pub banned_words_files: Vec<PathBuf>,
pub max_player_group_size: u32,
pub client_timeout: Duration,
}
impl Default for ServerSettings {
@ -47,6 +48,7 @@ impl Default for ServerSettings {
max_view_distance: Some(30),
banned_words_files: Vec::new(),
max_player_group_size: 6,
client_timeout: Duration::from_secs(40),
}
}
}
@ -113,6 +115,7 @@ impl ServerSettings {
* to use admin commands or not */
persistence_db_dir,
max_view_distance: None,
client_timeout: Duration::from_secs(180),
..load // Fill in remaining fields from server_settings.ron.
}
}

View File

@ -1,7 +1,7 @@
use super::SysTimer;
use crate::{
alias_validator::AliasValidator, client::Client, login_provider::LoginProvider,
persistence::character::CharacterLoader, ServerSettings, CLIENT_TIMEOUT,
persistence::character::CharacterLoader, ServerSettings,
};
use common::{
comp::{
@ -519,7 +519,7 @@ impl<'a> System<'a> for Sys {
// Update client ping.
if cnt > 0 {
client.last_ping = time.0
} else if time.0 - client.last_ping > CLIENT_TIMEOUT
} else if time.0 - client.last_ping > settings.client_timeout.as_secs() as f64
// Timeout
{
info!(?entity, "timeout error with client, disconnecting");
@ -529,7 +529,7 @@ impl<'a> System<'a> for Sys {
{
debug!(?entity, "postbox error with client, disconnecting");
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
} else if time.0 - client.last_ping > CLIENT_TIMEOUT * 0.5 {
} else if time.0 - client.last_ping > settings.client_timeout.as_secs() as f64 * 0.5 {
// Try pinging the client if the timeout is nearing.
client.notify(ServerMsg::Ping);
}