mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
fix weather_zone command, and only send local wind once every 30 ticks
This commit is contained in:
parent
b55038a526
commit
8f15dedc3b
@ -180,10 +180,29 @@ pub struct SiteInfoRich {
|
||||
struct WeatherLerp {
|
||||
old: (SharedWeatherGrid, Instant),
|
||||
new: (SharedWeatherGrid, Instant),
|
||||
local_weather: Weather,
|
||||
old_local_wind: (Vec2<f32>, Instant),
|
||||
new_local_wind: (Vec2<f32>, Instant),
|
||||
local_wind: Vec2<f32>,
|
||||
}
|
||||
|
||||
impl WeatherLerp {
|
||||
fn local_wind_update(&mut self, wind: Vec2<f32>) {
|
||||
self.old_local_wind = mem::replace(&mut self.new_local_wind, (wind, Instant::now()));
|
||||
}
|
||||
|
||||
fn update_local_wind(&mut self) {
|
||||
// Assumes updates are regular
|
||||
let t = (self.new_local_wind.1.elapsed().as_secs_f32()
|
||||
/ self
|
||||
.new_local_wind
|
||||
.1
|
||||
.duration_since(self.old_local_wind.1)
|
||||
.as_secs_f32())
|
||||
.clamp(0.0, 1.0);
|
||||
|
||||
self.local_wind = Vec2::lerp_unclamped(self.old_local_wind.0, self.new_local_wind.0, t);
|
||||
}
|
||||
|
||||
fn weather_update(&mut self, weather: SharedWeatherGrid) {
|
||||
self.old = mem::replace(&mut self.new, (weather, Instant::now()));
|
||||
}
|
||||
@ -192,6 +211,7 @@ impl WeatherLerp {
|
||||
// that updates come at regular intervals.
|
||||
fn update(&mut self, to_update: &mut WeatherGrid) {
|
||||
prof_span!("WeatherLerp::update");
|
||||
self.update_local_wind();
|
||||
let old = &self.old.0;
|
||||
let new = &self.new.0;
|
||||
if new.size() == Vec2::zero() {
|
||||
@ -218,10 +238,14 @@ impl WeatherLerp {
|
||||
|
||||
impl Default for WeatherLerp {
|
||||
fn default() -> Self {
|
||||
let old = Instant::now();
|
||||
let new = Instant::now();
|
||||
Self {
|
||||
old: (SharedWeatherGrid::new(Vec2::zero()), Instant::now()),
|
||||
new: (SharedWeatherGrid::new(Vec2::zero()), Instant::now()),
|
||||
local_weather: Weather::default(),
|
||||
old: (SharedWeatherGrid::new(Vec2::zero()), old),
|
||||
new: (SharedWeatherGrid::new(Vec2::zero()), new),
|
||||
old_local_wind: (Vec2::zero(), old),
|
||||
new_local_wind: (Vec2::zero(), new),
|
||||
local_wind: Vec2::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1715,7 +1739,15 @@ impl Client {
|
||||
.map(|v| v.0)
|
||||
}
|
||||
|
||||
pub fn weather_at_player(&self) -> Weather { self.weather.local_weather }
|
||||
pub fn weather_at_player(&self) -> Weather {
|
||||
self.position()
|
||||
.map(|p| {
|
||||
let mut weather = self.state.weather_at(p.xy());
|
||||
weather.wind = self.weather.local_wind;
|
||||
weather
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn current_chunk(&self) -> Option<Arc<TerrainChunk>> {
|
||||
let chunk_pos = Vec2::from(self.position()?)
|
||||
@ -2536,8 +2568,8 @@ impl Client {
|
||||
ServerGeneral::WeatherUpdate(weather) => {
|
||||
self.weather.weather_update(weather);
|
||||
},
|
||||
ServerGeneral::LocalWeatherUpdate(weather) => {
|
||||
self.weather.local_weather = weather;
|
||||
ServerGeneral::LocalWindUpdate(wind) => {
|
||||
self.weather.local_wind_update(wind);
|
||||
},
|
||||
ServerGeneral::SpectatePosition(pos) => {
|
||||
frontend_events.push(Event::SpectatePosition(pos));
|
||||
|
@ -17,7 +17,7 @@ use common::{
|
||||
trade::{PendingTrade, SitePrices, TradeId, TradeResult},
|
||||
uid::Uid,
|
||||
uuid::Uuid,
|
||||
weather::{SharedWeatherGrid, Weather},
|
||||
weather::SharedWeatherGrid,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -215,7 +215,7 @@ pub enum ServerGeneral {
|
||||
SiteEconomy(EconomyInfo),
|
||||
MapMarker(comp::MapMarkerUpdate),
|
||||
WeatherUpdate(SharedWeatherGrid),
|
||||
LocalWeatherUpdate(Weather),
|
||||
LocalWindUpdate(Vec2<f32>),
|
||||
/// Suggest the client to spectate a position. Called after client has
|
||||
/// requested teleport etc.
|
||||
SpectatePosition(Vec3<f32>),
|
||||
@ -340,7 +340,7 @@ impl ServerMsg {
|
||||
| ServerGeneral::SiteEconomy(_)
|
||||
| ServerGeneral::MapMarker(_)
|
||||
| ServerGeneral::WeatherUpdate(_)
|
||||
| ServerGeneral::LocalWeatherUpdate(_)
|
||||
| ServerGeneral::LocalWindUpdate(_)
|
||||
| ServerGeneral::SpectatePosition(_) => {
|
||||
c_type == ClientType::Game && presence.is_some()
|
||||
},
|
||||
|
@ -192,7 +192,7 @@ impl Client {
|
||||
| ServerGeneral::FinishedTrade(_)
|
||||
| ServerGeneral::MapMarker(_)
|
||||
| ServerGeneral::WeatherUpdate(_)
|
||||
| ServerGeneral::LocalWeatherUpdate(_)
|
||||
| ServerGeneral::LocalWindUpdate(_)
|
||||
| ServerGeneral::SpectatePosition(_) => {
|
||||
PreparedMsg::new(2, &g, &self.in_game_stream_params)
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
SettingError, WhitelistInfo, WhitelistRecord,
|
||||
},
|
||||
sys::terrain::NpcData,
|
||||
weather::WeatherSim,
|
||||
weather::WeatherJob,
|
||||
wiring,
|
||||
wiring::OutputFormula,
|
||||
Server, Settings, StateExt,
|
||||
@ -4474,11 +4474,14 @@ fn handle_weather_zone(
|
||||
let mut add_zone = |weather: weather::Weather| {
|
||||
if let Ok(pos) = position(server, client, "player") {
|
||||
let pos = pos.0.xy() / weather::CELL_SIZE as f32;
|
||||
server
|
||||
if let Some(weather_job) = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.write_resource::<WeatherSim>()
|
||||
.add_zone(weather, pos, radius, time);
|
||||
.write_resource::<Option<WeatherJob>>()
|
||||
.as_mut()
|
||||
{
|
||||
weather_job.queue_zone(weather, pos, radius, time);
|
||||
}
|
||||
}
|
||||
};
|
||||
match name.as_str() {
|
||||
|
@ -5,7 +5,7 @@ use specs::DispatcherBuilder;
|
||||
mod sim;
|
||||
mod tick;
|
||||
|
||||
pub use sim::WeatherSim;
|
||||
pub use tick::WeatherJob;
|
||||
|
||||
/// How often the weather is updated, in seconds
|
||||
const WEATHER_DT: f32 = 5.0;
|
||||
@ -18,8 +18,6 @@ pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
pub fn init(state: &mut State) {
|
||||
use crate::weather::sim::LightningCells;
|
||||
|
||||
use self::tick::WeatherJob;
|
||||
|
||||
state.ecs_mut().insert(None::<WeatherJob>);
|
||||
state.ecs_mut().insert(LightningCells::default());
|
||||
}
|
||||
|
@ -4,16 +4,17 @@ use common::{
|
||||
outcome::Outcome,
|
||||
resources::{DeltaTime, ProgramTime, TimeOfDay},
|
||||
slowjob::{SlowJob, SlowJobPool},
|
||||
weather::{SharedWeatherGrid, WeatherGrid},
|
||||
weather::{SharedWeatherGrid, Weather, WeatherGrid},
|
||||
};
|
||||
use common_ecs::{Origin, Phase, System};
|
||||
use common_net::msg::ServerGeneral;
|
||||
use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use specs::{Join, Read, ReadExpect, ReadStorage, Write, WriteExpect};
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteExpect};
|
||||
use std::{mem, sync::Arc};
|
||||
use vek::Vec2;
|
||||
use world::World;
|
||||
|
||||
use crate::client::Client;
|
||||
use crate::{client::Client, Tick};
|
||||
|
||||
use super::{
|
||||
sim::{LightningCells, WeatherSim},
|
||||
@ -31,6 +32,13 @@ pub struct WeatherJob {
|
||||
weather_tx: crossbeam_channel::Sender<(WeatherGrid, LightningCells, WeatherSim)>,
|
||||
weather_rx: crossbeam_channel::Receiver<(WeatherGrid, LightningCells, WeatherSim)>,
|
||||
state: WeatherJobState,
|
||||
qeued_zones: Vec<(Weather, Vec2<f32>, f32, f32)>,
|
||||
}
|
||||
|
||||
impl WeatherJob {
|
||||
pub fn queue_zone(&mut self, weather: Weather, pos: Vec2<f32>, radius: f32, time: f32) {
|
||||
self.qeued_zones.push((weather, pos, radius, time))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -38,8 +46,10 @@ pub struct Sys;
|
||||
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
Read<'a, TimeOfDay>,
|
||||
Read<'a, ProgramTime>,
|
||||
Read<'a, Tick>,
|
||||
Read<'a, DeltaTime>,
|
||||
Write<'a, LightningCells>,
|
||||
Write<'a, Option<WeatherJob>>,
|
||||
@ -58,8 +68,10 @@ impl<'a> System<'a> for Sys {
|
||||
fn run(
|
||||
_job: &mut common_ecs::Job<Self>,
|
||||
(
|
||||
entities,
|
||||
game_time,
|
||||
program_time,
|
||||
tick,
|
||||
delta_time,
|
||||
mut lightning_cells,
|
||||
mut weather_job,
|
||||
@ -87,6 +99,7 @@ impl<'a> System<'a> for Sys {
|
||||
weather_tx,
|
||||
weather_rx,
|
||||
state: WeatherJobState::Idle(sim),
|
||||
qeued_zones: Vec::new(),
|
||||
});
|
||||
|
||||
None
|
||||
@ -118,6 +131,9 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
let weather_tx = weather_job.weather_tx.clone();
|
||||
let game_time = *game_time;
|
||||
for (weather, pos, radius, time) in weather_job.qeued_zones.drain(..) {
|
||||
sim.add_zone(weather, pos, radius, time)
|
||||
}
|
||||
let job = slow_job_pool.spawn("WEATHER", move || {
|
||||
let mut grid = WeatherGrid::new(sim.size());
|
||||
let lightning_cells = sim.tick(game_time, &mut grid);
|
||||
@ -148,9 +164,11 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
|
||||
for (client, pos) in (&clients, &positions).join() {
|
||||
let weather = grid.get_interpolated(pos.0.xy());
|
||||
client.send_fallible(ServerGeneral::LocalWeatherUpdate(weather));
|
||||
for (entity, client, pos) in (&entities, &clients, &positions).join() {
|
||||
if entity.id() as u64 % 30 == tick.0 % 30 {
|
||||
let weather = grid.get_interpolated(pos.0.xy());
|
||||
client.send_fallible(ServerGeneral::LocalWindUpdate(weather.wind));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user