diff --git a/client/src/lib.rs b/client/src/lib.rs index 79ef38080f..78b70022ab 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -252,8 +252,10 @@ pub struct Client { tick: u64, state: State, - server_view_distance_limit: Option, + flashing_lights_enabled: bool, + /// Terrrain view distance + server_view_distance_limit: Option, view_distance: Option, lod_distance: f32, // TODO: move into voxygen @@ -731,6 +733,9 @@ impl Client { tick: 0, state, + + flashing_lights_enabled: true, + server_view_distance_limit: None, view_distance: None, lod_distance: 4.0, @@ -1003,6 +1008,10 @@ impl Client { self.lod_distance = lod_distance; } + pub fn set_flashing_lights_enabled(&mut self, flashing_lights_enabled: bool) { + self.flashing_lights_enabled = flashing_lights_enabled; + } + pub fn use_slot(&mut self, slot: Slot) { self.control_action(ControlAction::InventoryAction(InventoryAction::Use(slot))) } @@ -1764,14 +1773,10 @@ impl Client { // Lerp the clientside weather. self.weather.update(&mut self.state.weather_grid_mut()); - // Lerp towards the target time of day - this ensures a smooth transition for - // large jumps in TimeOfDay such as when using /time if let Some(target_tod) = self.target_time_of_day { let mut tod = self.state.ecs_mut().write_resource::(); - tod.0 = Lerp::lerp(tod.0, target_tod.0, dt.as_secs_f64()); - if tod.0 >= target_tod.0 { - self.target_time_of_day = None; - } + tod.0 = target_tod.0; + self.target_time_of_day = None; } // 4) Tick the client's LocalState diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 036cb728b2..d23bbc9f12 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -955,8 +955,14 @@ fn handle_time( Some("dusk") => { next_cycle(NaiveTime::from_hms(17, 0, 0).num_seconds_from_midnight() as f64) }, - Some(n) => match n.parse() { - Ok(n) => n, + Some(n) => match n.parse::() { + Ok(n) => { + if n < 0.0 { + return Err(format!("{} is invalid, cannot be negative.", n)); + } + // Seconds from next midnight + next_cycle(0.0) + n + }, Err(_) => match NaiveTime::parse_from_str(n, "%H:%M") { // Relative to current day Ok(time) => next_cycle(time.num_seconds_from_midnight() as f64), @@ -966,10 +972,18 @@ fn handle_time( .filter(|_| n.starts_with('u')) .and_then(|n| n.trim_start_matches('u').parse::().ok()) { - // Absolute time (i.e: since in-game epoch) - Some(n) => n as f64, + // Absolute time (i.e. from world epoch) + Some(n) => { + if (n as f64) < time_in_seconds { + return Err(format!( + "{} is before the current time, time cannot go backwards.", + n + )); + } + n as f64 + }, None => { - return Err(format!("{:?} is not a valid time.", n)); + return Err(format!("{} is not a valid time.", n)); }, }, }, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 5a20ddbb3f..9056ee1743 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -111,6 +111,7 @@ pub struct Scene { ambient_mgr: AmbientMgr, integrated_rain_vel: f32, + pub interpolated_time_of_day: f64, last_lightning: Option<(Vec3, f64)>, } @@ -134,12 +135,13 @@ pub struct SceneData<'a> { pub flashing_lights_enabled: bool, pub figure_lod_render_distance: f32, pub is_aiming: bool, + pub interpolated_time_of_day: f64, } impl<'a> SceneData<'a> { - pub fn get_sun_dir(&self) -> Vec3 { Globals::get_sun_dir(self.state.get_time_of_day()) } + pub fn get_sun_dir(&self) -> Vec3 { Globals::get_sun_dir(self.interpolated_time_of_day) } - pub fn get_moon_dir(&self) -> Vec3 { Globals::get_moon_dir(self.state.get_time_of_day()) } + pub fn get_moon_dir(&self) -> Vec3 { Globals::get_moon_dir(self.interpolated_time_of_day) } } /// Approximate a scalar field of view angle using the parameterization from @@ -339,6 +341,7 @@ impl Scene { ambience: ambient::load_ambience_items(), }, integrated_rain_vel: 0.0, + interpolated_time_of_day: 0.0, last_lightning: None, } } @@ -714,7 +717,23 @@ impl Scene { self.loaded_distance = loaded_distance; // Update light projection matrices for the shadow map. + + // When the target time of day and time of day have a large discrepancy + // (i.e two days), the linear interpolation causes brght flashing effects + // in the sky. This will snap the time of day to the target time of day + // for the client to avoid the flashing effect if flashing lights is + // disabled. + const DAY: f64 = 60.0 * 60.0 * 24.0; let time_of_day = scene_data.state.get_time_of_day(); + self.interpolated_time_of_day = if (self.interpolated_time_of_day - time_of_day).abs() + > DAY * 2.0 + && !scene_data.flashing_lights_enabled + { + time_of_day + } else { + Lerp::lerp(self.interpolated_time_of_day, time_of_day, dt as f64) + }; + let time_of_day = self.interpolated_time_of_day; let focus_pos = self.camera.get_focus_pos(); let focus_off = focus_pos.map(|e| e.trunc()); diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index a84ebceab6..4b9e223ff2 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1736,6 +1736,7 @@ impl PlayState for SessionState { .figure_lod_render_distance as f32, is_aiming, + interpolated_time_of_day: self.scene.interpolated_time_of_day, }; // Runs if either in a multiplayer server or the singleplayer server is unpaused @@ -1817,6 +1818,7 @@ impl PlayState for SessionState { weapon_trails_enabled: settings.graphics.weapon_trails_enabled, flashing_lights_enabled: settings.graphics.render_mode.flashing_lights_enabled, is_aiming: self.is_aiming, + interpolated_time_of_day: self.scene.interpolated_time_of_day, }; // Render world