aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-12-18 22:49:15 +0100
committermetamuffin <metamuffin@disroot.org>2025-12-18 22:49:18 +0100
commitcf3d5d44166e7214700b73d657aa10018167ae0c (patch)
tree9b74ed9e719b44bc8f8d312cdf4bb83651b20983
parent6832af5ee35b9d16668e1d34f191715f3755679f (diff)
downloadhurrycurry-cf3d5d44166e7214700b73d657aa10018167ae0c.tar
hurrycurry-cf3d5d44166e7214700b73d657aa10018167ae0c.tar.bz2
hurrycurry-cf3d5d44166e7214700b73d657aa10018167ae0c.tar.zst
only send movement packets if changes; bots send less inputs
-rw-r--r--server/bot/src/algos/customer.rs60
-rw-r--r--server/bot/src/pathfinding.rs69
-rw-r--r--server/bot/src/step.rs10
-rw-r--r--server/src/entity/player_portal.rs5
-rw-r--r--server/src/entity/player_portal_pair.rs6
-rw-r--r--server/src/server.rs24
6 files changed, 106 insertions, 68 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs
index fe665f47..ebc6e64a 100644
--- a/server/bot/src/algos/customer.rs
+++ b/server/bot/src/algos/customer.rs
@@ -17,7 +17,7 @@
*/
use crate::{
BotAlgo, PacketSink,
- pathfinding::{Path, find_path},
+ pathfinding::{HoldLocation, Path, find_path},
random_float,
};
use hurrycurry_game_core::Game;
@@ -50,19 +50,19 @@ enum CustomerState {
ticks: usize,
},
Waiting {
+ hold_location: HoldLocation,
demand: DemandIndex,
chair: IVec2,
- facing: Vec2,
timeout: f32,
origin: IVec2,
check: u8,
pinned: bool,
},
Eating {
+ hold_location: HoldLocation,
demand: DemandIndex,
table: IVec2,
progress: f32,
- chair: IVec2,
origin: IVec2,
},
Finishing {
@@ -148,10 +148,10 @@ impl CustomerState {
chair: *chair,
timeout,
demand,
- facing,
origin: *origin,
check: 0,
pinned: false,
+ hold_location: HoldLocation::new(chair.as_vec2(), facing),
};
let message_item = if !game.data.flags.disable_unknown_orders {
game.data
@@ -182,22 +182,17 @@ impl CustomerState {
} else {
#[cfg(feature = "debug_events")]
out.push(PacketS::Debug(path.debug(me)));
- out.push(PacketS::Movement {
- player: me,
- dir: path.next_direction(pos, dt) * 0.6,
- boost: false,
- pos: None,
- });
+ path.update(out, me, pos, dt, 0.6, false);
}
}
CustomerState::Waiting {
+ hold_location,
chair,
demand,
timeout,
origin,
check,
pinned,
- facing,
} => {
*timeout -= dt;
*check += 1;
@@ -271,7 +266,7 @@ impl CustomerState {
None
}
});
- if let Some(pos) = demand_pos {
+ if let Some(table) = demand_pos {
debug!("{me:?} -> eating");
let points = game.data.demands[demand.0].points;
out.push(PacketS::Communicate {
@@ -291,7 +286,7 @@ impl CustomerState {
player: me,
});
out.push(PacketS::Interact {
- target: Some(ItemLocation::Tile(pos)),
+ target: Some(ItemLocation::Tile(table)),
player: me,
hand: Hand(0),
});
@@ -306,28 +301,26 @@ impl CustomerState {
hand: Hand(0),
});
*self = CustomerState::Eating {
+ hold_location: HoldLocation::new(
+ chair.as_vec2(),
+ (table - *chair).as_vec2(),
+ ),
demand: *demand,
- table: pos,
+ table,
progress: 0.,
- chair: *chair,
origin: *origin,
};
return;
}
}
- out.push(PacketS::Movement {
- player: me,
- dir: dir_input(pos, *chair, *facing),
- boost: false,
- pos: None,
- });
+ hold_location.update(out, me, pos);
}
CustomerState::Eating {
+ hold_location,
demand,
table,
progress,
- chair,
origin,
} => {
let demand = &game.data.demands[demand.0];
@@ -346,12 +339,7 @@ impl CustomerState {
});
return;
}
- out.push(PacketS::Movement {
- player: me,
- dir: dir_input(pos, *chair, (*table - *chair).as_vec2()),
- boost: false,
- pos: None,
- });
+ hold_location.update(out, me, pos);
}
CustomerState::Finishing {
table,
@@ -398,24 +386,10 @@ impl CustomerState {
} else {
#[cfg(feature = "debug_events")]
out.push(PacketS::Debug(path.debug(me)));
- out.push(PacketS::Movement {
- player: me,
- dir: path.next_direction(pos, dt) * 0.6,
- boost: false,
- pos: None,
- });
+ path.update(out, me, pos, dt, 0.6, false);
}
}
CustomerState::Exited => (),
}
}
}
-
-fn dir_input(pos: Vec2, target: IVec2, facing: Vec2) -> Vec2 {
- let diff = (target.as_vec2() + 0.5) - pos;
- (if diff.length() > 0.3 {
- diff.normalize()
- } else {
- diff * 0.5
- }) + facing.clamp_length_max(1.) * 0.3
-}
diff --git a/server/bot/src/pathfinding.rs b/server/bot/src/pathfinding.rs
index 4aa7c2ff..f9f213fa 100644
--- a/server/bot/src/pathfinding.rs
+++ b/server/bot/src/pathfinding.rs
@@ -15,10 +15,14 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+use crate::PacketSink;
use hurrycurry_game_core::Game;
-use hurrycurry_protocol::glam::{IVec2, Vec2};
#[cfg(feature = "debug_events")]
-use hurrycurry_protocol::{DebugEvent, DebugEventDisplay, PlayerID};
+use hurrycurry_protocol::{DebugEvent, DebugEventDisplay};
+use hurrycurry_protocol::{
+ PacketS, PlayerID,
+ glam::{IVec2, Vec2},
+};
use log::{debug, trace};
use std::{
cmp::Ordering,
@@ -30,13 +34,39 @@ use std::{
pub struct Path {
segments: Vec<Vec2>,
seg_time: f32,
+ last_dir: Vec2,
+ last_boost: bool,
}
impl Path {
pub const EMPTY: Path = Path {
seg_time: 0.,
segments: Vec::new(),
+ last_boost: false,
+ last_dir: Vec2::ZERO,
};
+ pub fn update(
+ &mut self,
+ out: &mut PacketSink,
+ player: PlayerID,
+ position: Vec2,
+ dt: f32,
+ speed: f32,
+ allow_boost: bool,
+ ) {
+ let dir = speed * self.next_direction(position, dt);
+ let boost = allow_boost && self.is_stuck(0.5);
+ if dir.distance(self.last_dir) > 0.1 || boost != self.last_boost {
+ self.last_dir = dir;
+ self.last_boost = boost;
+ out.push(PacketS::Movement {
+ player,
+ dir,
+ boost,
+ pos: None,
+ });
+ }
+ }
pub fn next_direction(&mut self, position: Vec2, dt: f32) -> Vec2 {
if let Some(next) = self.segments.last().copied() {
trace!("next {next}");
@@ -171,5 +201,40 @@ pub fn find_path(game: &Game, from: IVec2, to: IVec2) -> Option<Path> {
Some(Path {
segments,
seg_time: 0.,
+ last_boost: false,
+ last_dir: Vec2::ZERO,
})
}
+
+#[derive(Debug, Clone)]
+pub struct HoldLocation {
+ target: Vec2,
+ facing: Vec2,
+ last_dir: Vec2,
+}
+impl HoldLocation {
+ pub fn new(target: Vec2, facing: Vec2) -> Self {
+ Self {
+ facing,
+ target,
+ last_dir: Vec2::ZERO,
+ }
+ }
+ pub fn update(&mut self, out: &mut PacketSink, player: PlayerID, pos: Vec2) {
+ let diff = (self.target + 0.5) - pos;
+ let dir = match diff.length() {
+ x if x < 0.3 => self.facing.clamp_length_max(1.) * 0.4, // TODO rotation not updating
+ x if x < 1.0 => diff.normalize() * 0.6,
+ _ => diff.normalize(),
+ };
+ if dir.distance(self.last_dir) > 0.1 {
+ self.last_dir = dir;
+ out.push(PacketS::Movement {
+ player,
+ dir,
+ boost: false,
+ pos: None,
+ });
+ }
+ }
+}
diff --git a/server/bot/src/step.rs b/server/bot/src/step.rs
index 6031439f..75e5d427 100644
--- a/server/bot/src/step.rs
+++ b/server/bot/src/step.rs
@@ -144,17 +144,9 @@ impl StepState {
.map(|p| p.movement.position)
.unwrap_or_default();
- let dir = self.path.next_direction(position, dt);
-
#[cfg(feature = "debug_events")]
out.push(PacketS::Debug(self.path.debug(self.me)));
-
- out.push(PacketS::Movement {
- player: self.me,
- dir,
- boost: self.path.is_stuck(0.5),
- pos: None,
- });
+ self.path.update(out, self.me, position, dt, 1., true);
}
}
}
diff --git a/server/src/entity/player_portal.rs b/server/src/entity/player_portal.rs
index a2653900..35733ca3 100644
--- a/server/src/entity/player_portal.rs
+++ b/server/src/entity/player_portal.rs
@@ -18,7 +18,7 @@
use super::{Entity, EntityContext};
use anyhow::Result;
use hurrycurry_locale::TrError;
-use hurrycurry_protocol::{PacketC, glam::Vec2};
+use hurrycurry_protocol::glam::Vec2;
#[derive(Debug, Default, Clone)]
pub struct PlayerPortal {
@@ -40,8 +40,7 @@ impl Entity for PlayerPortal {
.get_mut(&pid)
.ok_or(TrError::Plain("Player is missing".to_string()))?;
p.movement.position = self.to;
- c.packet_out
- .push_back(PacketC::MovementSync { player: pid });
+ p.movement_must_sync = true;
}
Ok(())
diff --git a/server/src/entity/player_portal_pair.rs b/server/src/entity/player_portal_pair.rs
index 9691ca05..fd28b774 100644
--- a/server/src/entity/player_portal_pair.rs
+++ b/server/src/entity/player_portal_pair.rs
@@ -19,7 +19,7 @@ use super::{Entity, EntityContext};
use anyhow::Result;
use hurrycurry_locale::TrError;
use hurrycurry_protocol::{
- PacketC, TileIndex,
+ TileIndex,
glam::{IVec2, Vec2, vec2},
};
@@ -104,7 +104,7 @@ impl Entity for PlayerPortalPair {
&& let Some(p) = c.game.players.get_mut(&player)
{
p.movement.position = self.b_f;
- c.packet_out.push_back(PacketC::MovementSync { player });
+ p.movement_must_sync = true;
}
if self.state == -1
@@ -113,7 +113,7 @@ impl Entity for PlayerPortalPair {
&& let Some(p) = c.game.players.get_mut(&player)
{
p.movement.position = self.a_f;
- c.packet_out.push_back(PacketC::MovementSync { player });
+ p.movement_must_sync = true;
}
Ok(())
diff --git a/server/src/server.rs b/server/src/server.rs
index b925a577..be5fee3f 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -528,7 +528,7 @@ impl Server {
let diff = pos - pd.movement.position;
pd.movement.position += diff.clamp_length_max(dt.as_secs_f32());
if diff.length() > 1. {
- replies.push(PacketC::MovementSync { player });
+ pd.movement_must_sync = true;
}
}
}
@@ -698,13 +698,21 @@ impl Server {
});
for (&pid, player) in &mut self.game.players {
- self.packet_out.push_back(PacketC::Movement {
- player: pid,
- pos: player.movement.position,
- dir: player.movement.input_direction,
- boost: player.movement.boosting,
- rot: player.movement.rotation,
- });
+ if player.movement_input_changed || player.movement_must_sync {
+ player.movement_input_changed = false;
+ self.packet_out.push_back(PacketC::Movement {
+ player: pid,
+ pos: player.movement.position,
+ dir: player.movement.input_direction,
+ boost: player.movement.boosting,
+ rot: player.movement.rotation,
+ });
+ if player.movement_must_sync {
+ player.movement_must_sync = false;
+ self.packet_out
+ .push_back(PacketC::MovementSync { player: pid });
+ }
+ }
}
let mut players_auto_release = Vec::new();