fix(reset): warp the player home instead of moving him silently
Some checks failed
.NET Core / build (push) Has been cancelled

MoveHomeAsync wrote PositionX/PositionY/CurrentMap/Rotation on the character
record directly, which is a partial copy of Player.PlaceAtGateAsync: it placed
the player but skipped removing him from the map and telling the client.

Player.Position is backed by those very fields, so the coordinates jumped on the
server while the client never got a map change. The client then interpolated a
walk to the new spot and the character visibly slid across the map after a reset.

WarpToAsync does the same placement plus the map removal and the map change
notification, and it handles respawning on the same map. It is the path every
other caller uses (duel room, gate NPCs, mini games, castle siege portal).

The existing tests all ran with MoveHome = false, which is why this path was
never covered. The new test pins the notification: it fails on the old code
because MapChangeAsync is never invoked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Acentech Dev
2026-07-17 00:26:04 +03:00
parent 2927be1ba9
commit 1de06d83ab
2 changed files with 65 additions and 6 deletions

View File

@@ -202,10 +202,12 @@ public class ResetCharacterAction
if (homeMapDef is { }
&& await this._player.GameContext.GetMapAsync((ushort)homeMapDef.Number).ConfigureAwait(false) is { SafeZoneSpawnGate: { } spawnGate })
{
this._player.SelectedCharacter.PositionX = (byte)Rand.NextInt(spawnGate.X1, spawnGate.X2);
this._player.SelectedCharacter.PositionY = (byte)Rand.NextInt(spawnGate.Y1, spawnGate.Y2);
this._player.SelectedCharacter.CurrentMap = spawnGate.Map;
this._player.Rotation = spawnGate.Direction;
// ADAMU-CUSTOM: warp instead of writing the position fields directly.
// The direct writes moved the player without removing him from the map or sending a
// map change, so the client was never told and animated a walk to the new spot: the
// character visibly slid across the map. WarpToAsync does the same placement plus the
// map removal and the client notification.
await this._player.WarpToAsync(spawnGate).ConfigureAwait(false);
}
}