aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/bot/Cargo.toml2
-rw-r--r--server/bot/src/main.rs59
-rw-r--r--server/client-lib/src/lib.rs44
-rw-r--r--server/client-lib/src/network/sync.rs14
-rw-r--r--server/protocol/src/lib.rs12
-rw-r--r--server/protocol/src/movement.rs19
-rw-r--r--server/src/entity/customers/mod.rs16
-rw-r--r--server/src/game.rs28
-rw-r--r--server/src/state.rs2
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:?}");