summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/entity/mod.rs12
-rw-r--r--server/src/entity/weather.rs51
-rw-r--r--server/src/game.rs23
-rw-r--r--server/src/lib.rs19
4 files changed, 99 insertions, 6 deletions
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index ad0bde6f..d042d458 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -19,6 +19,7 @@ pub mod conveyor;
pub mod customers;
pub mod item_portal;
pub mod player_portal;
+pub mod weather;
use crate::{data::ItemTileRegistry, game::Game, interaction::Recipe};
use anyhow::{anyhow, Result};
@@ -32,6 +33,7 @@ use item_portal::ItemPortal;
use player_portal::PlayerPortal;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, VecDeque};
+use weather::WeatherController;
pub trait EntityT: Clone {
fn tick(&mut self, game: &mut Game, packet_out: &mut VecDeque<PacketC>, dt: f32) -> Result<()>;
@@ -49,7 +51,13 @@ macro_rules! entities {
};
}
-entities!(Conveyor, ItemPortal, PlayerPortal, Customers);
+entities!(
+ Conveyor,
+ ItemPortal,
+ PlayerPortal,
+ Customers,
+ WeatherController
+);
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
@@ -71,6 +79,7 @@ pub enum EntityDecl {
to: Vec2,
},
Customers {},
+ Weather {},
}
pub fn construct_entity(
@@ -125,5 +134,6 @@ pub fn construct_entity(
.collect();
Entity::Customers(Customers::new(chairs, demands)?)
}
+ EntityDecl::Weather {} => Entity::WeatherController(WeatherController::default()),
})
}
diff --git a/server/src/entity/weather.rs b/server/src/entity/weather.rs
new file mode 100644
index 00000000..79ac364f
--- /dev/null
+++ b/server/src/entity/weather.rs
@@ -0,0 +1,51 @@
+use super::EntityT;
+use crate::{game::Game, InterpolateExt};
+use hurrycurry_protocol::PacketC;
+use rand::{random, seq::IndexedRandom, thread_rng};
+use std::{
+ collections::VecDeque,
+ time::{Duration, Instant},
+};
+
+#[derive(Clone, Debug)]
+pub struct WeatherController {
+ next_event: Instant,
+ event: usize,
+}
+
+impl Default for WeatherController {
+ fn default() -> Self {
+ Self {
+ next_event: Instant::now() + Duration::from_secs(10),
+ event: Default::default(),
+ }
+ }
+}
+impl EntityT for WeatherController {
+ fn tick(
+ &mut self,
+ game: &mut Game,
+ _packet_out: &mut VecDeque<PacketC>,
+ dt: f32,
+ ) -> anyhow::Result<()> {
+ if self.next_event < Instant::now() {
+ self.next_event += Duration::from_secs_f32(30. + random::<f32>() * 40.);
+ if self.event > 0 {
+ self.event = 0;
+ } else {
+ self.event = *[0, 0, 1, 2].choose(&mut thread_rng()).unwrap();
+ }
+ }
+
+ let (rain, wind) = match self.event {
+ 0 => (0., 0.),
+ 1 => (0.7, 0.),
+ 2 => (0., 0.7),
+ _ => (1., 1.),
+ };
+ game.environment.wind.exp_to(wind, dt * 0.05);
+ game.environment.rain.exp_to(rain, dt * 0.15);
+ eprintln!("{:#?}", game.environment);
+ Ok(())
+ }
+}
diff --git a/server/src/game.rs b/server/src/game.rs
index d649d87e..69272159 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -25,8 +25,8 @@ use anyhow::{anyhow, bail, Result};
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
movement::MovementBase,
- ClientGamedata, ItemIndex, ItemLocation, Menu, Message, PacketC, PacketS, PlayerID,
- RecipeIndex, Score, TileIndex,
+ ClientGamedata, Environment, ItemIndex, ItemLocation, Menu, Message, PacketC, PacketS,
+ PlayerID, RecipeIndex, Score, TileIndex,
};
use log::{info, warn};
use std::{
@@ -76,6 +76,8 @@ pub struct Game {
end: Option<Instant>,
pub lobby: bool,
+ pub environment_next_update: Instant,
+ pub environment: Environment,
pub score_changed: bool,
pub score: Score,
}
@@ -93,11 +95,13 @@ impl Game {
data: Gamedata::default().into(),
players: HashMap::new(),
tiles: HashMap::new(),
+ environment_next_update: Instant::now(),
walkable: HashSet::new(),
end: None,
entities: Arc::new(RwLock::new(vec![])),
players_spatial_index: SpatialIndex::default(),
score: Score::default(),
+ environment: Environment::default(),
score_changed: false,
}
}
@@ -117,6 +121,9 @@ impl Game {
neighbors: [None, None, None, None],
})
}
+ self.score = Score::default();
+ self.end = None;
+ self.environment = Environment::default();
self.walkable.clear();
}
pub fn load(
@@ -215,6 +222,7 @@ impl Game {
.collect(),
},
});
+ out.push(PacketC::UpdateEnvironment(self.environment.clone()));
for (&id, player) in &self.players {
out.push(PacketC::AddPlayer {
id,
@@ -589,9 +597,16 @@ impl Game {
}
}
+ let now = Instant::now();
+
+ if self.environment_next_update < now {
+ packet_out.push_back(PacketC::UpdateEnvironment(self.environment.clone()));
+ self.environment_next_update += Duration::from_secs(5);
+ }
+
if let Some(end) = self.end {
- self.score.time_remaining = (end - Instant::now()).as_secs_f64();
- if end < Instant::now() {
+ self.score.time_remaining = (end - now).as_secs_f64();
+ if end < now {
let relative_score = (self.score.points * 100) / self.data.score_baseline.max(1);
self.score.stars = match relative_score {
100.. => 3,
diff --git a/server/src/lib.rs b/server/src/lib.rs
index a59aad11..2cbcc10b 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -20,5 +20,22 @@ pub mod data;
pub mod entity;
pub mod game;
pub mod interaction;
-pub mod state;
pub mod spatial_index;
+pub mod state;
+
+use hurrycurry_protocol::glam::Vec2;
+
+pub trait InterpolateExt {
+ fn exp_to(&mut self, target: Self, dt: f32);
+}
+impl InterpolateExt for Vec2 {
+ fn exp_to(&mut self, target: Self, dt: f32) {
+ self.x = target.x + (self.x - target.x) * (-dt).exp();
+ self.y = target.y + (self.y - target.y) * (-dt).exp();
+ }
+}
+impl InterpolateExt for f32 {
+ fn exp_to(&mut self, target: Self, dt: f32) {
+ *self = target + (*self - target) * (-dt).exp();
+ }
+}