diff --git a/server/src/lib.rs b/server/src/lib.rs index bd0ba1567b..f73147b480 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -96,7 +96,7 @@ use prometheus_hyper::Server as PrometheusServer; use specs::{join::Join, Builder, Entity as EcsEntity, Entity, SystemData, WorldExt}; use std::{ i32, - ops::{Deref, DerefMut, Range}, + ops::{Deref, DerefMut}, sync::Arc, time::{Duration, Instant}, }; @@ -137,7 +137,7 @@ impl Default for SpawnPoint { // server-side. This is independent of the client's view distance and exists to // avoid exploits such as small view distance chunk reloading and also to keep // various mechanics working fluidly (i.e: not unloading nearby entities). -pub const MIN_VD: Range = 5..6; +pub const MIN_VD: u32 = 6; // Tick count used for throttling network updates // Note this doesn't account for dt (so update rate changes with tick rate) diff --git a/server/src/sys/msg/terrain.rs b/server/src/sys/msg/terrain.rs index 43e6cc4b9a..a68cd5f85b 100644 --- a/server/src/sys/msg/terrain.rs +++ b/server/src/sys/msg/terrain.rs @@ -114,7 +114,7 @@ impl<'a> System<'a> for Sys { .0 .xy() .map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32); - for rpos in Spiral2d::new().take((crate::MIN_VD.start as usize + 1).pow(2)) { + for rpos in Spiral2d::new().take((crate::MIN_VD as usize + 1).pow(2)) { let key = player_chunk + rpos; if terrain.get_key(key).is_none() { events.push(ServerEvent::ChunkRequest(entity, key)); diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index f8e7f1ae56..932f98a27d 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -495,13 +495,17 @@ pub fn chunk_in_vd( terrain: &TerrainGrid, vd: u32, ) -> bool { + // This fuzzy threshold prevents chunks rapidly unloading and reloading when + // players move over a chunk border. + const UNLOAD_THRESHOLD: u32 = 2; + let player_chunk_pos = terrain.pos_key(player_pos.map(|e| e as i32)); let adjusted_dist_sqr = (player_chunk_pos - chunk_pos) - .map(|e: i32| (e.abs() as u32).saturating_sub(2)) + .map(|e: i32| e.abs() as u32) .magnitude_squared(); - adjusted_dist_sqr <= vd.max(crate::MIN_VD.end).pow(2) + adjusted_dist_sqr <= (vd.max(crate::MIN_VD) + UNLOAD_THRESHOLD).pow(2) } fn is_spawn_chunk(chunk_pos: Vec2, spawn_pos: SpawnPoint, terrain: &TerrainGrid) -> bool {