diff options
author | metamuffin <metamuffin@disroot.org> | 2024-08-11 01:30:59 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-08-11 01:35:05 +0200 |
commit | 218da36b4f963a5dfcd619d543cb95c5c196d214 (patch) | |
tree | 244ecd10f4ca3d9798cedf7149394a1d4827b5d9 /server | |
parent | f753629acd906ff7acd42a18a266cc93a883330c (diff) | |
download | hurrycurry-218da36b4f963a5dfcd619d543cb95c5c196d214.tar hurrycurry-218da36b4f963a5dfcd619d543cb95c5c196d214.tar.bz2 hurrycurry-218da36b4f963a5dfcd619d543cb95c5c196d214.tar.zst |
update movement in protocol and all clients
Diffstat (limited to 'server')
-rw-r--r-- | server/bot/Cargo.toml | 2 | ||||
-rw-r--r-- | server/bot/src/main.rs | 59 | ||||
-rw-r--r-- | server/client-lib/src/lib.rs | 44 | ||||
-rw-r--r-- | server/client-lib/src/network/sync.rs | 14 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 12 | ||||
-rw-r--r-- | server/protocol/src/movement.rs | 19 | ||||
-rw-r--r-- | server/src/entity/customers/mod.rs | 16 | ||||
-rw-r--r-- | server/src/game.rs | 28 | ||||
-rw-r--r-- | server/src/state.rs | 2 |
9 files changed, 149 insertions, 47 deletions
diff --git a/server/bot/Cargo.toml b/server/bot/Cargo.toml index 157472ae..cd0ac383 100644 --- a/server/bot/Cargo.toml +++ b/server/bot/Cargo.toml @@ -5,4 +5,6 @@ edition = "2021" [dependencies] hurrycurry-client-lib = { path = "../client-lib", features = ["tokio-network"] } +hurrycurry-protocol = { path = "../protocol" } log = "0.4.22" +anyhow = "1.0.86" diff --git a/server/bot/src/main.rs b/server/bot/src/main.rs index 0b625703..61cef1f9 100644 --- a/server/bot/src/main.rs +++ b/server/bot/src/main.rs @@ -16,6 +16,59 @@ */ -fn main() { - -}
\ No newline at end of file +use std::{thread::sleep, time::Duration}; + +use anyhow::Result; +use hurrycurry_client_lib::{network::sync::Network, Game}; +use hurrycurry_protocol::{glam::Vec2, PacketC, PacketS, PlayerID}; + +fn main() -> Result<()> { + let mut network = Network::connect("ws://127.0.0.1")?; + + let mut game = Game::default(); + + network.queue_out.push_back(PacketS::Join { + name: "bot".to_string(), + character: 1, + }); + + let mut bots = Vec::new(); + + loop { + let dt = 1. / 50.; + + network.poll()?; + + while let Some(packet) = network.queue_in.pop_front() { + match &packet { + PacketC::Joined { id } => bots.push(Bot::new(*id)), + _ => (), + } + game.apply_packet(packet); + } + + for b in &bots { + network.queue_out.push_back(PacketS::Movement { + player: b.id, + dir: Vec2::ONE, + boost: true, + pos: None, + }); + } + + sleep(Duration::from_secs_f32(dt)); + } +} + +pub struct Bot { + id: PlayerID, +} + +impl Bot { + pub fn new(id: PlayerID) -> Self { + Self { id } + } + pub fn tick(&self, game: &Game) { + if let Some(player) = game.players.get(&self.id) {} + } +} diff --git a/server/client-lib/src/lib.rs b/server/client-lib/src/lib.rs index 649e71b2..d949ac6e 100644 --- a/server/client-lib/src/lib.rs +++ b/server/client-lib/src/lib.rs @@ -15,6 +15,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#![feature(map_many_mut)] pub mod network; pub mod spatial_index; @@ -63,6 +64,22 @@ pub struct Game { pub score: Score, } +impl Default for Game { + fn default() -> Self { + Self { + data: Default::default(), + tiles: HashMap::new(), + walkable: HashSet::new(), + players: HashMap::new(), + players_spatial_index: SpatialIndex::default(), + end: None, + lobby: false, + environment_effects: HashSet::new(), + score: Score::default(), + } + } +} + impl Game { pub fn apply_packet(&mut self, packet: PacketC) { match packet { @@ -90,16 +107,17 @@ impl Game { PacketC::RemovePlayer { id } => { self.players.remove(&id); } - PacketC::Position { + PacketC::Movement { player, pos, rot, - boosting, + boost, + dir, } => { if let Some(p) = self.players.get_mut(&player) { + p.movement.input(dir, boost); p.movement.position = pos; p.movement.rotation = rot; - p.movement.boosting = boosting; } } @@ -159,6 +177,26 @@ impl Game { _ => (), } } + + pub fn tick(&mut self, dt: f32) { + self.score.time_remaining -= dt as f64; + self.score.time_remaining -= self.score.time_remaining.max(0.); + + for (&pid, player) in &mut self.players { + player.movement.update(&self.walkable, dt); + self.players_spatial_index + .update_entry(pid, player.movement.position); + } + + self.players_spatial_index.all(|p1, pos1| { + self.players_spatial_index.query(pos1, 2., |p2, _pos2| { + if let Some([a, b]) = self.players.get_many_mut([&p1, &p2]) { + a.movement.collide(&mut b.movement, dt) + } + }) + }); + } + pub fn get_item(&mut self, location: ItemLocation) -> &mut Option<Item> { match location { ItemLocation::Tile(pos) => &mut self.tiles.get_mut(&pos).unwrap().item, diff --git a/server/client-lib/src/network/sync.rs b/server/client-lib/src/network/sync.rs index e8aa08de..3a475e01 100644 --- a/server/client-lib/src/network/sync.rs +++ b/server/client-lib/src/network/sync.rs @@ -80,7 +80,7 @@ impl Network { }) } - pub fn poll(&mut self) { + pub fn poll(&mut self) -> anyhow::Result<()> { loop { self.queue_in.extend(match self.sock.read() { Ok(Message::Text(packet)) => match serde_json::from_str(&packet) { @@ -131,18 +131,16 @@ impl Network { for packet in self.queue_out.drain(..) { debug!("-> {packet:?}"); if self.use_bincode { - self.sock - .write(Message::Binary( - bincode::encode_to_vec(&packet, BINCODE_CONFIG).unwrap(), - )) - .unwrap(); + self.sock.write(Message::Binary( + bincode::encode_to_vec(&packet, BINCODE_CONFIG).unwrap(), + ))?; } else { self.sock - .write(Message::Text(serde_json::to_string(&packet).unwrap())) - .unwrap(); + .write(Message::Text(serde_json::to_string(&packet).unwrap()))?; } } self.sock.flush().unwrap(); + Ok(()) } } diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 1a4e41a9..8f8e9784 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -30,7 +30,7 @@ pub use glam; pub mod movement; -pub const VERSION: (u32, u32) = (3, 0); +pub const VERSION: (u32, u32) = (4, 0); pub const BINCODE_CONFIG: Configuration<LittleEndian, Varint, Limit<4096>> = standard().with_limit(); @@ -94,8 +94,8 @@ pub enum PacketS { Movement { player: PlayerID, #[bincode(with_serde)] - direction: Vec2, - boosting: bool, + dir: Vec2, + boost: bool, #[bincode(with_serde)] pos: Option<Vec2>, }, @@ -155,12 +155,14 @@ pub enum PacketC { RemovePlayer { id: PlayerID, }, - Position { + Movement { player: PlayerID, #[bincode(with_serde)] pos: Vec2, rot: f32, - boosting: bool, + #[bincode(with_serde)] + dir: Vec2, + boost: bool, }, MoveItem { from: ItemLocation, diff --git a/server/protocol/src/movement.rs b/server/protocol/src/movement.rs index dad9d300..ebcc627d 100644 --- a/server/protocol/src/movement.rs +++ b/server/protocol/src/movement.rs @@ -29,7 +29,8 @@ const BOOST_DURATION: f32 = 0.3; const BOOST_RESTORE: f32 = 0.5; pub struct MovementBase { - pub direction: Vec2, + pub input_direction: Vec2, + pub input_boost: bool, pub position: Vec2, pub facing: Vec2, pub rotation: f32, @@ -41,8 +42,9 @@ pub struct MovementBase { impl MovementBase { pub fn new(position: Vec2) -> Self { Self { + input_direction: Vec2::ZERO, + input_boost: false, position, - direction: Vec2::ZERO, facing: Vec2::X, velocity: Vec2::ZERO, boosting: false, @@ -50,8 +52,13 @@ impl MovementBase { rotation: 0., } } - pub fn update(&mut self, map: &HashSet<IVec2>, direction: Vec2, mut boost: bool, dt: f32) { - self.direction = direction.clamp_length_max(1.); + pub fn input(&mut self, direction: Vec2, boost: bool) { + self.input_boost = boost; + self.input_direction = direction; + } + pub fn update(&mut self, map: &HashSet<IVec2>, dt: f32) { + let mut boost = self.input_boost; + let direction = self.input_direction.clamp_length_max(1.); if direction.length() > 0.1 { self.facing = direction + (self.facing - direction) * (-dt * 10.).exp(); } @@ -74,8 +81,8 @@ impl MovementBase { pub fn movement_packet(&self, player: PlayerID) -> PacketS { PacketS::Movement { pos: Some(self.position), - boosting: self.boosting, - direction: self.direction, + boost: self.input_boost, + dir: self.input_direction, player, } } diff --git a/server/src/entity/customers/mod.rs b/server/src/entity/customers/mod.rs index 0bb3f918..97b94942 100644 --- a/server/src/entity/customers/mod.rs +++ b/server/src/entity/customers/mod.rs @@ -102,7 +102,9 @@ impl EntityT for Customers { match state { CustomerState::Entering { path, chair } => { - playerdata.direction = path.next_direction(playerdata.position()); + playerdata + .movement + .input(path.next_direction(playerdata.position()), false); if path.is_done() { let demand = DemandIndex(random::<usize>() % self.demands.len()); self.cpackets.push_back(PacketS::Communicate { @@ -123,7 +125,9 @@ impl EntityT for Customers { demand, timeout, } => { - playerdata.direction = (chair.as_vec2() + 0.5) - playerdata.position(); + playerdata + .movement + .input((chair.as_vec2() + 0.5) - playerdata.position(), false); *timeout -= dt; if *timeout <= 0. { self.cpackets.push_back(PacketS::Communicate { @@ -203,7 +207,9 @@ impl EntityT for Customers { progress, chair, } => { - playerdata.direction = (chair.as_vec2() + 0.5) - playerdata.position(); + playerdata + .movement + .input((chair.as_vec2() + 0.5) - playerdata.position(), false); let demand = &self.demands[demand.0]; *progress += dt / demand.duration; if *progress >= 1. { @@ -234,7 +240,9 @@ impl EntityT for Customers { } } CustomerState::Exiting { path } => { - playerdata.direction = path.next_direction(playerdata.position()); + playerdata + .movement + .input(path.next_direction(playerdata.position()), false); if path.is_done() { info!("{player:?} -> leave"); self.cpackets.push_back(PacketS::Leave { player }); diff --git a/server/src/game.rs b/server/src/game.rs index c010c8b8..5af9658e 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -61,8 +61,6 @@ pub struct Player { pub communicate_persist: Option<Message>, pub movement: MovementBase, - pub direction: Vec2, - pub boost: bool, pub last_position_update: Instant, } @@ -178,7 +176,8 @@ impl Game { } else { self.data.chef_spawn }, - direction: Vec2::ZERO, + input_direction: Vec2::ZERO, + input_boost: false, facing: Vec2::X, rotation: 0., velocity: Vec2::ZERO, @@ -186,8 +185,6 @@ impl Game { stamina: 0., }, last_position_update: Instant::now(), - boost: false, - direction: Vec2::ZERO, communicate_persist: None, interacting: None, name: name.clone(), @@ -298,7 +295,8 @@ impl Game { } else { self.data.chef_spawn }, - direction: Vec2::ZERO, + input_direction: Vec2::ZERO, + input_boost: false, facing: Vec2::X, rotation: 0., velocity: Vec2::ZERO, @@ -306,8 +304,6 @@ impl Game { stamina: 0., }, last_position_update: Instant::now(), - boost: false, - direction: Vec2::ZERO, communicate_persist: None, interacting: None, name: name.clone(), @@ -358,8 +354,8 @@ impl Game { } PacketS::Movement { pos, - boosting, - direction, + boost, + dir: direction, player, } => { let pd = self @@ -367,8 +363,7 @@ impl Game { .get_mut(&player) .ok_or(anyhow!("player does not exist"))?; - pd.direction = direction; - pd.boost = boosting; + pd.movement.input(direction, boost); if let Some(pos) = pos { let dt = pd.last_position_update.elapsed(); @@ -541,9 +536,7 @@ impl Game { } for (&pid, player) in &mut self.players { - player - .movement - .update(&self.walkable, player.direction, player.boost, dt); + player.movement.update(&self.walkable, dt); self.players_spatial_index .update_entry(pid, player.movement.position); @@ -558,10 +551,11 @@ impl Game { }); for (&pid, player) in &mut self.players { - packet_out.push_back(PacketC::Position { + packet_out.push_back(PacketC::Movement { player: pid, pos: player.movement.position, - boosting: player.movement.boosting, + dir: player.movement.input_direction, + boost: player.movement.boosting, rot: player.movement.rotation, }); diff --git a/server/src/state.rs b/server/src/state.rs index 43ca29bd..526f70aa 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -106,7 +106,7 @@ impl State { ); } while let Some(p) = self.packet_out.pop_front() { - if matches!(p, PacketC::UpdateMap { .. } | PacketC::Position { .. }) { + if matches!(p, PacketC::UpdateMap { .. } | PacketC::Movement { .. }) { trace!("-> {p:?}"); } else { debug!("-> {p:?}"); |