Skip to content

Commit 4102151

Browse files
committed
Stop movement should remember last position
1 parent f0c7447 commit 4102151

File tree

2 files changed

+42
-15
lines changed

2 files changed

+42
-15
lines changed

game/src/packets/from_client/move_to_location.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ impl Message<RequestMoveToLocation> for PlayerClient {
4444
) -> anyhow::Result<()> {
4545
//TODO check with geodata if the location is valid.
4646

47-
// Get the current position for distance validation
48-
let player = self.try_get_selected_char()?;
49-
let (current_x, current_y, current_z) = (player.get_x(), player.get_y(), player.get_z());
47+
// Get the effective current position for distance validation
48+
// This aligns with start_movement starting point logic (mid-move retargets included)
49+
let (current_x, current_y, current_z) = self.effective_current_position()?;
5050

5151
// Calculate distance
5252
let Some(distance) = calculate_distance(
5353
current_x, current_y, current_z, msg.x_to, msg.y_to, msg.z_to,
5454
) else {
55+
let player = self.try_get_selected_char()?;
5556
warn!(
5657
"Player {} attempted movement causing coordinate overflow. Pos: ({},{},{}) -> Dest: ({},{},{})",
5758
player.char_model.name,
@@ -68,6 +69,7 @@ impl Message<RequestMoveToLocation> for PlayerClient {
6869
// Check against max distance from config
6970
let cfg = self.controller.get_cfg();
7071
if cfg.max_movement_distance > 0 && distance > f64::from(cfg.max_movement_distance) {
72+
let player = self.try_get_selected_char()?;
7173
warn!(
7274
"Player {} attempted to move excessive distance: {:.2} (max: {})",
7375
player.char_model.name, distance, cfg.max_movement_distance

game/src/pl_client.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub struct PlayerClient {
6868
pub packet_sender: Option<ActorRef<ConnectionActor<Self>>>,
6969
session_key: Option<SessionKey>,
7070
user: Option<user::Model>,
71-
pub movement_state: Option<MovementState>,
71+
movement_state: Option<MovementState>,
7272
}
7373

7474
impl Debug for PlayerClient {
@@ -80,6 +80,17 @@ impl Debug for PlayerClient {
8080
}
8181
}
8282
impl PlayerClient {
83+
/// Get the player's effective current position used as a starting point for movement
84+
/// If there is an existing movement, we return its interpolated current position;
85+
/// otherwise we fall back to the stored player coordinates.
86+
pub(crate) fn effective_current_position(&self) -> anyhow::Result<(i32, i32, i32)> {
87+
if let Some(movement) = &self.movement_state {
88+
Ok(movement.calculate_current_position())
89+
} else {
90+
let player = self.try_get_selected_char()?;
91+
Ok((player.get_x(), player.get_y(), player.get_z()))
92+
}
93+
}
8394
pub fn new(ip: Ipv4Addr, controller: Arc<GameController>, db_pool: DBPool) -> Self {
8495
Self {
8596
status: ClientStatus::Connected,
@@ -327,16 +338,13 @@ impl PlayerClient {
327338
dest_z: i32,
328339
actor_ref: ActorRef<PlayerClient>,
329340
) -> anyhow::Result<(i32, i32, i32)> {
330-
// Cancel existing movement if any and get the current position
331-
let (current_x, current_y, current_z) =
332-
if let Some(mut existing_movement) = self.movement_state.take() {
333-
existing_movement.cancel_task();
334-
existing_movement.calculate_current_position()
335-
} else {
336-
// Use a player's stored position
337-
let player = self.try_get_selected_char()?;
338-
(player.get_x(), player.get_y(), player.get_z())
339-
};
341+
// Compute effective current position consistent with validation logic
342+
let (current_x, current_y, current_z) = self.effective_current_position()?;
343+
344+
// Cancel existing movement if any
345+
if let Some(mut existing_movement) = self.movement_state.take() {
346+
existing_movement.cancel_task();
347+
}
340348

341349
// Get player speed
342350
let player = self.try_get_selected_char()?;
@@ -399,8 +407,25 @@ impl PlayerClient {
399407
/// Stop current movement and return the current interpolated position
400408
pub fn stop_movement(&mut self) -> Option<(i32, i32, i32)> {
401409
if let Some(mut movement) = self.movement_state.take() {
410+
// Calculate current position at the time of stopping
411+
let (x, y, z) = movement.calculate_current_position();
412+
413+
// Stop periodic task
402414
movement.cancel_task();
403-
Some(movement.calculate_current_position())
415+
416+
// Persist the position to the selected character so server state matches
417+
match self.try_get_selected_char_mut() {
418+
Ok(player) => {
419+
if let Err(err) = player.set_location(x, y, z) {
420+
error!("Failed to persist player position on stop_movement: {err}");
421+
}
422+
}
423+
Err(err) => {
424+
error!("Failed to get selected character on stop_movement: {err}");
425+
}
426+
}
427+
428+
Some((x, y, z))
404429
} else {
405430
None
406431
}

0 commit comments

Comments
 (0)